bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


patrons_disseny

Diferències

Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.

Enllaç a la visualització de la comparació

patrons_disseny [2022/11/24 07:47]
albert_palacios_jimenez creat
patrons_disseny [2022/11/24 08:20] (actual)
albert_palacios_jimenez
Línia 6: Línia 6:
 ---- ----
  
-==== Exemples ====+==== Patrons de disseny ==== 
 + 
 +- Fa referència a solucions de programació usades habitualment al dissenyar software. 
 + 
 +- Habitualment els patrons de disseny es consideren bones pràctiques a la hora de programar. 
 + 
 +- A vegades es critica alguns patrons de disseny ja que poden ser resultat d’un mal disseny del software, en aquests casos s’anomenen ‘anti-patrons’ 
 + 
 +==== Paradigmes de programació ==== 
 + 
 +Els diferents llenguatges de programació ofereixen diferents eines per solucionar els problemes que surten a la hora de dissenyar el software. En la programació imperativa hi ha dos paradigmes: 
 + 
 +- **Programació procedural**, que agrupa les instruccions en procediments i les dades en estructures 
 + 
 +<code c> 
 +struct persona0 { 
 +    String nom; 
 +    String edat; 
 +
 + 
 +function aniversari () { 
 +    persona0.edat += 1; 
 +
 +</code> 
 + 
 +- **Programació orientada en objectes**, en què les instruccions formen part de l’estat de l’objecte en què es declaren 
 + 
 +<code java> 
 +public class Persona { 
 +    String nom; 
 +    String edat; 
 +    public void aniversari () { 
 +        edat += 1; 
 +    } 
 +
 +</code> 
 + 
 +==== Orientació a objectes ==== 
 + 
 +És un paradigma en què la programació es fa definint objectes, que contenen dades i codi. 
 + 
 +- **Dades**, o propietats de l’objecte 
 + 
 +- **Codi**, procediments que operen sobre les dades (funcions) 
 + 
 + 
 +Cal distingir entre les definicions i els objectes funcionals 
 + 
 +- **Classes**, defineixen els objectes (les seves dades i funcions) 
 + 
 +<code java> 
 +public class Poligon { 
 + int num_vertex = 1; 
 + String nom = “linia” 
 + public Poligon (v1, n1) { 
 + num_vertex = v1; 
 + nom = n1; } 
 +
 +</code>  
 + 
 +- **Instàncies**, objectes existents amb un estat (dades) diferents a altres objectes de la mateixa classe 
 + 
 +<code java> 
 +public static void Main (String[] args) { 
 + Poligon pL = new Poligon(2, “linia”); 
 + Poligon pT = new Poligon(3, “triangle”); 
 + Poligon pQ = new Poligon(4, “quadrat”); 
 +
 +</code> 
 + 
 +pL, pT i pQ són instàncies de la classe Poligon 
 + 
 +== Java, extends == 
 + 
 +Quan volem fer servir les propietats i mètodes d’una classe pare fem servir ‘**extends**’.  
 + 
 +També podem sobre-escriure els mètodes de la classe filla amb ‘**@Override**' 
 + 
 +<code java> 
 +package SuperClass; 
 +public class SuperClass { 
 +   public int getNb() { 
 +       return 1; 
 +   } 
 +   public int getNb2() { 
 +    return 2; 
 +   } 
 +
 + 
 +package SuperClass; 
 +public class SubClass extends SuperClass { 
 +   @Override 
 +   public int getNb2() { 
 +    return 3; 
 +   } 
 +
 + 
 +package SuperClass; 
 +public class Main { 
 +   public static void main(String args[]){ 
 +       SubClass s = new SubClass(); 
 +       System.out.println(s.getNb()); //returns 1 
 +       System.out.println(s.getNb2()); //returns 3 
 +     
 +       SuperClass sup = new SuperClass(); 
 +       System.out.println(sup.getNb()); //returns 1 
 +       System.out.println(sup.getNb2()); //returns 2 
 +   } 
 +
 +</code> 
 + 
 +== Java, implements == 
 + 
 +Una clase abstracta que agrupa mètodes buits, que s’han d’implementar en altres classes 
 + 
 + 
 +<code java> 
 +package Animals; 
 +interface Animal { 
 +   public void animalSound(); 
 +   public void sleep(); 
 +
 + 
 +package Animals; 
 +class Anec implements Animal { 
 +   public void animalSound() { 
 +     System.out.println("L'anec fa: quac quac"); 
 +   } 
 +
 + 
 +package Animals; 
 +class Gos implements Animal { 
 +   public void animalSound() { 
 +     System.out.println("El gos diu: guau guau"); 
 +   } 
 +   public void sleep() { 
 +     System.out.println("Zzz"); 
 +   } 
 +
 + 
 +package Animals; 
 +public class Main { 
 +   public static void main(String args[]){ 
 +       Anec a = new Anec(); 
 +       Gos g = new Gos(); 
 + 
 +       a.animalSound(); 
 +       g.animalSound(); 
 +   } 
 +
 +</code> 
 + 
 +== Java, mètodes abstractes == 
 + 
 +Les classes abstractes es declaren sense implementació, no es poden instanciar però se’n poden fer subclasses. Pot implementar algún mètode. 
 + 
 +<code java> 
 +package Animals2; 
 +abstract class Animal { 
 +   public abstract void animalSound(); 
 +   public void sleep() { 
 +     System.out.println("Zzz"); 
 +   } 
 +
 + 
 +package Animals2; 
 +class Anec extends Animal { 
 +   public void animalSound() { 
 +     System.out.println("L'anec fa: quac quac"); 
 +   } 
 +
 + 
 +package Animals2; 
 +class Gos extends Animal { 
 +   public void animalSound() { 
 +     System.out.println("El gos diu: guau guau"); 
 +   } 
 +   public void sleep() { 
 +     System.out.println("Zzz"); 
 +   } 
 +
 + 
 +package Animals2; 
 +public class Main { 
 +   public static void main(String args[]){ 
 +       Anec a = new Anec(); 
 +       Gos g = new Gos(); 
 +       a.animalSound(); 
 +       g.animalSound(); 
 +   } 
 +
 +</code> 
 + 
 +==== Prototype ==== 
 + 
 +Prototype és un patró que ens permet crear còpies d’objectes sense que dependre de les seves classes. 
 + 
 +Quan volem una còpia exacte d’un objecte tenim algun problema: 
 + 
 +- Els objectes poden tenir mètodes privats que no podem veure 
 + 
 +- Com que cal conèixer la classe original, pot ser que implementi una altre classe 
 + 
 +El patró “prototype” delega el procés de clonar un objecte als propis objectes que estan essent clonats. 
 + 
 +Per fer-ho, es crea una “interficie” amb almenys el mètode “clone” que crea un objecte de la classe actual amb tots els valors de l’objecte antic 
 + 
 +Quan es fa servir Prototype? 
 + 
 +- Quan el teu codi no hagi de dependre de les classes que necessites copiar 
 + 
 +- Imagina que tens una clase complexa que és complicada de configurar, prototype permet tenir diferents objectes configurats llestos per clonar i usar 
 + 
 +Amb prototype hem de crear el mètode 'clone()' que s'encarrega de fer una instància que és còpia exacte del mateix element. Per fer-ho cal tenir un constructor que accepti la pròpia Classe com a paràmetre. 
 +<code java> 
 +import java.util.Objects; 
 + 
 +public abstract class Poligon { 
 +     
 +    public int x; 
 +    public int y; 
 +    public String color; 
 + 
 +    public Poligon() {} 
 + 
 +    public Poligon(Poligon target) { 
 +        if (target != null) { 
 +            this.x = target.x; 
 +            this.y = target.y; 
 +            this.color = target.color; 
 +        } 
 +    } 
 + 
 +    public abstract Poligon clone(); 
 + 
 +    @Override 
 +    public boolean equals(Object object2) { 
 +        if (!(object2 instanceof Poligon)) return false; 
 +        Poligon cast2 = (Poligon) object2; 
 +        return cast2.x == x && cast2.y == y && cast2.color.equals(color); 
 +    } 
 +
 +</code> 
 + 
 +<code java> 
 +public class Cercle extends Poligon { 
 +     
 +    public int radius; 
 + 
 +    public Cercle() { 
 +    } 
 + 
 +    public Cercle(Cercle target) { 
 +        super(target); 
 +        if (target != null) { 
 +            this.radius = target.radius; 
 +        } 
 +    } 
 + 
 +    @Override 
 +    public Poligon clone() { 
 +        return new Cercle(this); 
 +    } 
 + 
 +    @Override 
 +    public boolean equals(Object object2) { 
 +        if (!(object2 instanceof Poligon) || !super.equals(object2)) return false; 
 +        Cercle cast2 = (Cercle) object2; 
 +        return cast2.radius == radius; 
 +    } 
 +
 +</code> 
 + 
 +== Exemple de Prototype == 
 + 
 +{{ ::designpatterns-exemple_prototype.zip |}} 
 + 
 +==== Factory ==== 
 + 
 +Substituir la creació d’objectes a través de ‘new’ per crides a metodes ‘factory’ específics de cada classe. 
 + 
 +Els objectes es segueixen creant amb ‘new’, però es fa de manera interna al mètode ‘factory’ 
 + 
 +El objectes creats a través de ‘factory’ s’anomenen ‘products’ 
 + 
 +Quina és la motivació de Factory? 
 + 
 +- Els clients d’una llibreria no tenen que saber com funciona aquesta llibreria, o fins i tot el tipus d’objecte o constructors que es fan servir. 
 + 
 +- Amb factory tens un ‘product’ que declara una interfície comú a tots els objectes i les seves subclasses 
 + 
 +- Cal que hi hagi una classe ‘creator’ que té el mètode per fabricar ‘products’ 
 + 
 +Quan es fa servir factory? 
 + 
 +- Quan no sabem amb quins tipus d’objectes i dependencies haurà de treballar el nostre codi 
 + 
 +- Quan volem donar maneres d’extendre els components de la nostre llibreria 
 + 
 +- Quan volem estalviar recursos del sistema, aprofitant objectes enlloc de refentlos cada vegada 
 + 
 +En Java Factory es pot implementar a través de: 
 + 
 +- interface i classes que implementen les seves funcions 
 + 
 +- amb classes derivades (extends) i sobreescrivint les funcions necessàries 
 + 
 +Transportation.java 
 +<code java> 
 +public interface Transportation { 
 +    void deliverPackage(); 
 +
 +</code> 
 + 
 +FactoryTransportation.java 
 +<code java> 
 +public class FactoryTransportation { 
 + 
 +    public static Transportation getTransportation(String method) { 
 + 
 + if("ship".equalsIgnoreCase(method))  
 +            return new TransportationShip(); 
 + else if("truck".equalsIgnoreCase(method))  
 +            return new TransportationTruck(); 
 +        else if("van".equalsIgnoreCase(method))  
 +            return new TransportationVan(); 
 + 
 +        return null; 
 +
 + 
 +    public static void deliver (Transportation transport) { 
 +        transport.deliverPackage(); 
 +    } 
 +
 +</code> 
 + 
 +TransportationShip.java 
 +<code java> 
 +public class TransportationShip implements Transportation { 
 + 
 +    @Override 
 +    public void deliverPackage() { 
 +        System.out.println("Package is traveling across the ocean"); 
 +    } 
 +
 +</code> 
 + 
 +TransportationTruck.java 
 +<code java> 
 +public class TransportationTruck implements Transportation { 
 + 
 +    @Override 
 +    public void deliverPackage() { 
 +        System.out.println("Highway traveling"); 
 +    } 
 +
 +</code> 
 + 
 +== Exemple de Factory == 
 + 
 +{{ ::designpatterns-exemple_factory.zip |}} 
 + 
 +==== Singleton ==== 
 + 
 +Singleton assegura que només hi ha una instància d’una classe determinada 
 + 
 +Crees un objecte, si al cap d’una estona tones a crear un objecte d’aquella classe reps l'original enlloc del nou 
 + 
 +Permet accedir un objecte de manera global en un programa, protegint-lo de sobre-escriptures 
 + 
 +Com es fa? 
 + 
 +- Posar el constructor de la classe com a ‘private’ 
 + 
 +- Fer un mètode de creació ‘static’ que funciona com a constructor, però: 
 + 
 +  * El primer cop crida al constructor privat 
 +  *          
 +  * La resta de vegades, retorna l’objecte creat originalment 
 +         
 +Avantages: 
 + 
 +- Assegura que només hi ha una instància de la classe 
 + 
 +- Es pot accedir a l’objecte de manera global 
 + 
 +- Només s’inicia el primer cop 
 + 
 +Crítiques: 
 + 
 +- Es considera un ‘anti-patró’ que pot amagar un mal disseny de l’aplicació 
 + 
 +- En entorns amb threads cal assegurar que diversos fils no creen un objecte ‘singelton’ diverses vegades 
 + 
 +Exemple de Singleton: 
 + 
 +<code java> 
 +public final class ExempleSingleton { 
 +   
 +   private static ExempleSingleton instance; 
 +   public String value; 
 + 
 +   private ExempleSingleton(String value) { 
 +       this.value = value; 
 +   } 
 + 
 +   public static ExempleSingleton getInstance(String value) { 
 +       if (instance == null) { 
 +           instance = new ExempleSingleton(value); 
 +       } 
 +       return instance; 
 +   } 
 +
 +</code> 
 + 
 +Els Singletons també es poden 'hackejar', aquest és un exemple de com ignorar un Singleton per crear diverses instàncies: 
 + 
 +<code java> 
 +ExempleSingleton instanceOne = ExempleSingleton.getInstance("Hola"); 
 +ExempleSingleton instanceTwo = null; 
 +try { 
 +    Constructor[] constructors = ExempleSingleton.class.getDeclaredConstructors(); 
 +    for (Constructor constructor : constructors) { 
 +        //Below code will destroy the singleton pattern 
 +        constructor.setAccessible(true); 
 +        instanceTwo = (ExempleSingleton) constructor.newInstance("Adeu"); 
 +        break; 
 +    } 
 +} catch (Exception e) { e.printStackTrace();
 +</code> 
 + 
 +Què passa amb els objectes serialitzables? 
 + 
 +Tot i que hi ha maneres d’implementar Singleton en objectes serialitzables, és fàcil trencar l’esquema i crear diverses instàncies serialitzant i des-serialitzant els objectes cada vegada que es vol una instància nova. 
 + 
 +== Exemple de Singleton == 
 + 
 +{{ ::designpatterns-exemple_singleton.zip |}} 
 + 
 +==== DAO, Data Access Object ==== 
 + 
 +DAO es fa servir per separar la manera de guardar les dades i la l’estructura lògica amb la que s’hi treballa a nivell de programació. 
 + 
 +Una interfície base DAO defineix les funcions que implementen tots els objectes DAO 
 + 
 +Cada objecte DAO implementa la transformació entre la seva Classe i on estan emmagatzemades les dades 
 + 
 +Una manera habitual de definir quines funcions ha de implementar DAO és CRUD, que significa: 
 + 
 +- Create 
 + 
 +- Read 
 + 
 +- Update 
 + 
 +- Delete 
 + 
 +I són les operacions més habituals al treballar amb models de dades 
 + 
 +<code java> 
 +public interface Dao<T>
 + 
 +   void add(T t); // Equival a Create 
 + 
 +   T get(int id); // Equival a Read 
 +   ArrayList<T> getAll(); 
 + 
 +   void update(int id, T t); 
 + 
 +   void delete(int id); 
 +   
 +   void print(); 
 +
 +</code> 
 + 
 +Avantatges de DAO 
 + 
 +- Simplifica el treball dels programadors al abstreure l’estructura de dades de l’arquitectura del programa 
 + 
 +- Unifica la manera de fer les crides pels diferents tipus d’objectes independentment de com es guarden les seves dades 
 + 
 +Inconvenients: 
 + 
 +- A vegades es defineixen massa funcions DAO fent que sigui difícil de mantenir o impossible d’aplicar a totes les dades per igual 
 + 
 +- Resta flexibilitat, fent que algunes crides/consultes a la base de dades no puguin estar optimitzades 
 + 
 +- Separar la lògica de les dades pot implicar necessitar operacions “extra” per guardar les modificacions del model de dades 
 + 
 +== Exemple de DAO == 
 + 
 +{{ ::designpatterns-exemple_dao.zip |}} 
 + 
 +==== Observer ==== 
 + 
 +Es crida a un mètode quan una variable cambia de valor.  
 + 
 +Tradicionalment un objecte, manté una llista d’observadors que criden a mètodes quan hi ha canvis a l’estat de l’objecte (valors de les variables). 
 + 
 +No hi ha una manera específica d’implementar l’observer, alguns llenguatges l’implementen de base, altres tenen llibreries específiques i normalment el programador s’ho implementa com millor li convé. 
 + 
 +Usos més habituals d'Observer: 
 + 
 +- En interfícies gràfiques quan un usuari canvia un ‘input’ (text, select, checkbox, …) per executar funcions que s'actualitzen les dades cap a una base de dades remota o algun altre element visual de la eina. 
 + 
 +- Quan les dades canvien remotament i rebem els nous valors, aquests han d’actualitzar la interfície gràfica automàticament. O executar processos que tractin aquestes noves dades rebudes adeqüadament. 
 + 
 +- Quan s’observa una carpeta d’arxius o un arxius i si hi ha canvis s’executa una acció (normalment ho fa un ‘thread’ paral·lel al procés) 
 + 
 +En java cal definir l'acció a fer quan hi han canvis, es fa a través de la funció "**propertyChange**": 
 + 
 +<code java> 
 +Observable<Integer> obsNum = new Observable<Integer>(0) { 
 +            @Override 
 +            public void propertyChange(Integer oldValue, Integer newValue) { 
 +                System.out.printf("obsNum ha canviat de %s cap a %s\n", oldValue, newValue); 
 +            }             
 +        }; 
 +</code> 
 + 
 +Observable.java 
 +<code java> 
 +public abstract class Observable<T>
 + 
 +    private T value; 
 + 
 +    public Observable(T value) { 
 +        this.value = value; 
 +    } 
 + 
 +    public T getValue() { 
 +        return value; 
 +    } 
 + 
 +    public void setValue(T value) { 
 +        T oldValue = this.value; 
 +        this.value = value; 
 +        this.propertyChange(oldValue, value); 
 +    } 
 + 
 +    public abstract void propertyChange(T oldValue, T newValue); 
 +
 +</code> 
 + 
 +Cada classe que vol observar alguna propietat necessita una llista d'observadors tipus **PropertyChangeSupport** 
 + 
 +<code java> 
 +import java.beans.PropertyChangeListener; 
 +import java.beans.PropertyChangeSupport; 
 + 
 +public class CotxeEvents { 
 +    private PropertyChangeSupport llistaObservers = new PropertyChangeSupport(this); 
 + 
 +    private CotxeEstats estat; 
 +    private int gasolina; 
 + 
 +    CotxeEvents () { 
 +        this.estat = CotxeEstats.ATURAT; 
 +        this.gasolina = 3; 
 +    } 
 + 
 +    public void addPropertyChangeListener(String name, PropertyChangeListener listener) { 
 +        llistaObservers.addPropertyChangeListener(name, listener); 
 +    } 
 + 
 +    public void removePropertyChangeListener(String name, PropertyChangeListener listener) { 
 +        llistaObservers.removePropertyChangeListener(name, listener); 
 +    } 
 + 
 +    public void setEstat (CotxeEstats newValue) { 
 +        CotxeEstats oldValue = this.estat; 
 +        if (oldValue != newValue) { 
 +            if (newValue != CotxeEstats.ATURAT) { 
 +                this.setGasolina(this.gasolina - 1); 
 +            } 
 +            if (this.gasolina > 0) { 
 +                this.estat = newValue; 
 +                llistaObservers.firePropertyChange("estat", oldValue, newValue); 
 +            } 
 +        } 
 +    } 
 + 
 +    public void setGasolina (int newValue) { 
 +        int oldValue = this.gasolina; 
 +        if (newValue > 0) { 
 +            this.gasolina = newValue; 
 +        } else { 
 +            this.gasolina = 0; 
 +            this.setEstat(CotxeEstats.ATURAT); 
 +        } 
 +        if (oldValue != this.gasolina) { 
 +            llistaObservers.firePropertyChange("gasolina", oldValue, newValue); 
 +        } 
 +    } 
 +
 + 
 +</code>  
 + 
 +== Exemple de Observer == 
 + 
 +{{ ::designpatterns-exemples_observer.zip |}} 
patrons_disseny.1669276055.txt.gz · Darrera modificació: 2022/11/24 07:47 per albert_palacios_jimenez