Píndoles de programació orientada a objectes

Conceptes de POO

Abstracció

L'abstracció amaga la complexitat a l'usuari i només mostra la informació rellevant. Els detalls d'un mètode abstracte són implementats de forma separa per cada classe.

Objectius: reusabilitat de codi, flexibilitat d'implementació, herència múltiple.

Java: classes abstractes (abstracció parcial) i interfícies (abstracció total).

Sintaxi: abstract (classes abstractes) i interface, implements (interfícies).

Encapsulació

L'encapsulació lliga les dades i els mètodes relacionats dins d'una classe. També protegeix les dades fent els camps privats i donant accés a ells només mitjançant els mètodes relacionats.

Objectius: protecció de dades, llegibilitat del codi.

Java: camps privats i públics amb getters i setters.

Sintaxi: private, setX(), getX().

Herència

L'herència permet que una classe fill hereti les característiques (camps i mètodes) d'una altra classe pare. En Java, una classe només pot estendre una classe.

Objectius: reusabilitat de codi, llegibilitat del codi.

Java: Classe pare i class fill.

Sintaxi: extends.

Polimorfisme

El polimorfisme permet utilitzar la mateixa estructura de codi de diferents formes. Les classes Java poden tenir diferents versions del mateix mètode si l'estructura dels paràmetres (signatura del mètode) són diferents.

Objectius: millor implementació de l'herència, flexibilitat del codi.

Java: sobrecàrrega de mètode (estàtic) i sobreescriptura de mètode (dinàmic).

Sintaxi: myMethod() myMethod(int x) myMetyhod(int x, String y) (estàtic) i ParentClass.myMethod() ChildClass.myMethod() (dinàmic).

Quan fer herència

L'herència només s'ha d'utilitzar quan:

  1. Les dues classes es troben en el mateix domini lògic
  2. La subclasse és un subtipus adequat de la superclasse
  3. La implementació de la superclasse és necessària o apropiada per a la subclasse
  4. Les millores realitzades per la subclasse són principalment additives.

Associació, agregació i composició

Associació

Agregació: Wheel pot existir sense Car

Associació navegable des de Child cap a Parent

Composició: Heart no pot existir sense Human

Patrons de disseny

Un patró de disseny és una solució general a un problema comú i recurrent en el disseny de programari. Un patró de disseny no és un disseny acabat que es pot transformar directament en codi; és una descripció o plantilla per resoldre un problema que es pot utilitzar en moltes situacions diferents.

Tenim algunes categories generals:

  • De comportament: identifiquen patrons de comunicació entre objectes.
  • Estructurals: faciliten el disseny quan s'han d'establir relacions entre entitats.
  • Creacionals: relacionats amb mecanismes de creació d'objectes de la forma més adient per cada cas.
  • Concurrència: tracten el paradigma de programació multifil.

A continuació es mostren alguns patrons importants. Dificultat: senzilla (*), intermèdia (**), alta (***).

Patrons de comportament

Command (**)

El patró de comandaments encapsula una sol·licitud com a objecte, de manera que us permetrà parametrizar altres objectes amb diferents peticions, cues o peticions de registre i donar suport a les operacions no desitjables.

Iterator (*)

El patró Iterator proporciona una manera d’accedir als elements d’un objecte agregat seqüencialment sense exposar la seva representació subjacent.

Exemples: java.util.Iterator i java.util.Enumeration

Observer (*)

El patró de l'observador defineix una dependència entre molts objectes de manera que quan un objecte canvia d'estat, tots els seus dependents són notificats i actualitzats automàticament.

Exemples: java.util.Observer i java.util.EventListener

State (**)

El patró d'estat permet a un objecte alterar el seu comportament quan canvia el seu estat intern. L'objecte semblarà canviar de classe.

Strategy (*)

El patró d’estratègia s’utilitza quan tenim diversos algorismes per a una tasca específica i el client decideix que s’utilitzi la implementació real en temps d’execució.

Exemples: Collections.sort() amb el paràmetre Comparator

Template method (*)

El patró de mètode de plantilla defineix l’esquelet d’un algorisme d’un mètode, diferint alguns passos a subclasses. El mètode de plantilla permet que les subclasses redefinis certs passos d’un algorisme sense canviar l’estructura de l’algoritme.

Exemple: construcció d'una casa de fusta o de vidre

Visitor (**)

El patró de disseny del visitant és una manera de separar un algorisme d’una estructura d’objectes on opera. Un resultat pràctic d’aquesta separació és la possibilitat d’afegir noves operacions a les estructures d’objectes existents sense modificar les estructures.

Exemple: la cistella de la compra

Patrons estructurals

Adapter (*)

El patró d'adaptador converteix la interfície d'una classe en una altra interfície que els clients esperen. L’adaptador permet que les classes treballin conjuntament, que d’una altra manera no podrien ser a causa d’una interfície incompatible.

Exemple: un capità que només pot utilitzar barques de rem i no pot navegar

Composite (**)

El patró compost us permet compondre objectes en estructures d’arbre per representar jerarquies parcials. Composite permet als clients tractar objectes individuals i composicions d'objectes de manera uniforme.

Decorator (*)

El patró decorador atribueix dinàmicament responsabilitats addicionals a un objecte. Els decoradors proporcionen una alternativa flexible a la subclasse per ampliar la funcionalitat.

Exemple: trol decorat amb una porra

Facade (*)

El patró de façanes proporciona una interfície unificada i més senzilla a un conjunt d’interfícies d’un subsistema. La façana defineix una interfície de més alt nivell que facilita la utilització del subsistema.

Exemple: treballadors de la mina d'or

Proxy (*)

El patró de proxy proporciona un substitut per a un altre objecte per controlar-ne l'accés.

Exemple: els tres mags que entren a la torre

Patrons creacionals

Factory (*)

El patró de mètode de fàbrica defineix una interfície per crear un objecte, però permet que les subclasses decideixin quina classe s'inicia. El mètode de fàbrica permet diferir la instància de classe a subclasses.

Exemple: el regne que necessita tres objectes temàtics

Singleton (*)

El patró de Singleton assegura que una classe només té una instància i li proporciona un punt d'accés global.

Exemple: només pot haver una torre d'ivori