Link Cerca Menu Expand Document

Píndoles POO

Conceptes de POO

Abstracció

L’abstracció amaga la complexitat a l’usuari i només mostra la informació rellevant. Permet centrar-nos en el “què” en lloc del “com”. 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 (estat) fent els camps privats i donant accés a ells només mitjançant els mètodes relacionats que implementen les regles de negoci i invariants.

Objectius: protecció de dades (estat), llegibilitat del codi.

Java: camps privats i mètodes públics (només els exposats).

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

Herència

Amb l’objectiu de reusar codi, l’herència permet que una classe fill hereti les característiques (camps i mètodes) d’una altra classe pare.

Objectius: reusabilitat de codi, llegibilitat del codi.

Java: Classe pare i class fill. Alternativa vàlida: patrons de composició i delegació.

Sintaxi: extends.

Polimorfisme

El polimorfisme permet substituir i estendre la funcionalitat d’objectes que tenen una mateixa interfície per uns altres durant el temps d’execució (dynamic binding).

Objectius: llegibilitat del codi, flexibilitat del codi.

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

Sintaxi: myMethod() myMethod(int x) myMethod(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 superclasse és un contracte (interfície o classe abstracta)
  4. La implementació de la superclasse és necessària o apropiada per a la subclasse
  5. Les millores realitzades per la subclasse són principalment additives.

Generalització, associació, agregació i composició

  1. Herència de Number i implementació de Comparable
  2. Associació entre Child1 i Parent1
  3. Associació navegable des de Child2 cap a Parent2
  4. Agregació: Wheel pot existir sense Car
  5. Composició: Heart no pot existir sense Human
  6. Dependència: Object1 usa l’Object2

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.

Patrons de comportament

Command

El patró command 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 operacions reversibles.

Tenim dos actors principals: el Client crea el ConcreteCommand i assigna el seu Receiver. L’Invoker té Commands que pot executar.

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ó observer 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.EventListener

State

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

El Context pot tenir un nombre de States. Quan cridem request(), el que fem es cridar el handle corresponent del State actual. Un Client no coneix el funcionament intern dels States.

Strategy

El patró strategy 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ó.

És molt similar a State, però és el Client qui habitualment escull la Strategy. Exemples: Collections.sort() amb el paràmetre Comparator

Dependency Injection

El patró de Dependency Injection permet a un objecte rebre les instàncies d’altres objectes de que depèn. Això permet que el client no s’hagi de referir a instàncies concretes, seguint el principi d’inversió de dependència. S’utilitza per implementar el principi de la inversió de control (IoC) mitjançant un contenidor.

Hi ha tres tipus d’injecció: Constructor, Setter i Interface.

  • Constructor: li diem al contenidor quina implementació s’utilitza per als paràmetres del constructor, que poden ser interfícies.
  • Setter: li diem al contenidor quines propietats (amb setters) cal instanciar d’un cert objecte.
  • Interface: li diem al contenidor que el nostre client rebrà les dependències mitjançant un mètode (del tipus setService).

Per utilitzar-los, cal configurar el contenidor. Es pot fer programàticament o mitjançant un arxiu de configuració.

L’objecte que injecta les dependències es diu injector, i els objectes de que depèn solen ser serveis.

Service Locator

El Service Locator és una alternativa al Dependency Injector, amb la particularitat que el codi client té una dependència del contenidor, que utilitza per localitzar tots els serveis que necessita. És a dir, no es produeix la injecció automàtica.

No es tracta d’una Factory, ja que no crea els serveis cada cop, només si cal. Es tracta més bé d’un registre.

Template method

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

El templateMethod fa ús del subMethod. Exemple: construcció d’una casa de fusta o de vidre

Patrons estructurals

Adapter

El patró adapter converteix la interfície d’una classe en una altra interfície que els clients esperen. L’adaptador permet que les classes treballin conjuntament, tot i tenir interfícies incompatibles.

El ConcreteAdapter està composat amb l’Adaptee, que li permet una operació addicional: adaptedOperation. Exemple: un capità que només pot utilitzar barques de rem i no pot navegar

Composite

El patró composite 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.

Tant els objectes individuals com els composats poden ser tractats igual amb operation.

Decorator

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

Podem afegir un comportament al ConcreteDecorator. Exemple: trol decorat amb una porra

Facade

El patró facade 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, seguint el principi del “Least knowledge”.

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.

Qualsevol Client pot tractar el Proxy com el RealSubject, ja que implementen Subject. Exemple: els tres mags que entren a la torre

Patrons creacionals

Separa la construcció d’un objecte complex de la seva representació, de forma que el mateix procés de construcció pot generar diferents representacions.

Builder

Factory method

Factory method defineix una interfície per crear un objecte, però permet que les subclasses decideixin quina classe s’inicia. Permet diferir la instància de classe a subclasses.

El mètode factoryMethod és abstracte, i s’encarrega de crear Products. Permet seguir el principi de “Dependency inversion”: evitar dependències de tipus concrets. 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

Referències