bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


Barra lateral

ASIX Administració de Sistemes Informàtics i Xarxes
Tots els mòduls del cicle
MP01 Implantació de sistemes operatius
Totes les UFs del modul
MP02 Gestió de bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Fonaments de maquinari
Totes les UFs del modul
MP06 Administració de sistemes operatius
Totes les UFs del modul
MP07 Planificació i administració de xarxes
Totes les UFs del modul
MP08 Serveis de xarxa i Internet
Totes les UFs del modul
MP09 Implantació d'aplicacions web
Totes les UFs del modul
MP10 Administració de sistemes gestors de bases de dades
Totes les UFs del modul
MP11 Seguretat i alta disponibilitat
Totes les UFs del modul
MP12 Formació i orientació laboral
Totes les UFs del modul
MP13 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP14 Projecte
Totes les UFs del modul
DAM Desenvolupament d’aplicacions multiplataforma
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Accés a dades
Totes les UFs del modul
MP07 Desenvolupament d’interfícies
Totes les UFs del modul
MP08 Programació multimèdia i dispositius mòbils
Totes les UFs del modul
MP09 Programació de serveis i processos
Totes les UFs del modul
MP10 Sistemes de gestió empresarial
Totes les UFs del modul
MP11 Formació i orientació laboral
Totes les UFs del modul
MP12 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP13 Projecte de síntesi
Totes les UFs del modul
MPDual Mòdul Dual / Projecte
DAW Desenvolupament d’aplicacions web
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació
Totes les UFs del modul
MP04 Llenguatge de marques i sistemes de gestió d’informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Desenvolupament web en entorn client
Totes les UFs del modul
MP07 Desenvolupament web en entorn servidor
Totes les UFs del modul
MP08 Desplegament d'aplicacions web
Totes les UFs del modul
MP09 Disseny d'interfícies web
Totes les UFs del modul
MP10 Formació i Orientació Laboral
Totes les UFs del modul
MP11 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP12 Projecte de síntesi
Totes les UFs del modul
SMX Sistemes Microinformàtics i Xarxes
Tots els mòduls del cicle
MP01 Muntatge i manteniment d’equips
Totes les UFs del modul
MP02 Sistemes Operatius Monolloc
Totes les UFs del modul
MP03 Aplicacions ofimàtiques
Totes les UFs del modul
MP04 Sistemes operatius en xarxa
Totes les UFs del modul
MP05 Xarxes locals
Totes les UFs del modul
MP06 Seguretat informàtica
Totes les UFs del modul
MP07 Serveis de xarxa
Totes les UFs del modul
MP08 Aplicacions Web
Totes les UFs del modul
MP09 Formació i Orientació Laboral
Totes les UFs del modul
MP10 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP11 Anglès
Totes les UFs del modul
MP12 Síntesi
Totes les UFs del modul
CETI Ciberseguretat en Entorns de les Tecnologies de la Informació
Tots els mòduls del cicle
CiberOT Ciberseguretat en Entorns d'Operació
Tots els mòduls del cicle
patrons_disseny

Patrons de disseny


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

struct persona0 {
    String nom;
    String edat;
}
 
function aniversari () {
    persona0.edat += 1;
}

- Programació orientada en objectes, en què les instruccions formen part de l’estat de l’objecte en què es declaren

public class Persona {
    String nom;
    String edat;
    public void aniversari () {
        edat += 1;
    }
}

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)

public class Poligon {
	int num_vertex = 1;
	String nom = “linia”
	public Poligon (v1, n1) {
	num_vertex = v1;
	nom = n1; }
}

- Instàncies, objectes existents amb un estat (dades) diferents a altres objectes de la mateixa classe

public static void Main (String[] args) {
	Poligon pL = new Poligon(2, “linia”);
	Poligon pT = new Poligon(3, “triangle”);
	Poligon pQ = new Poligon(4, “quadrat”);
}

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'

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
   }
}
Java, implements

Una clase abstracta que agrupa mètodes buits, que s’han d’implementar en altres classes

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();
   }
}
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.

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();
   }
}

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.

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);
    }
}
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;
    }
}
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

public interface Transportation {
    void deliverPackage();
}

FactoryTransportation.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();
    }
}

TransportationShip.java

public class TransportationShip implements Transportation {
 
    @Override
    public void deliverPackage() {
        System.out.println("Package is traveling across the ocean");
    }
}

TransportationTruck.java

public class TransportationTruck implements Transportation {
 
    @Override
    public void deliverPackage() {
        System.out.println("Highway traveling");
    }
}
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:

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;
   }
}

Els Singletons també es poden 'hackejar', aquest és un exemple de com ignorar un Singleton per crear diverses instàncies:

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(); }

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

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();
}

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»:

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);
            }            
        };

Observable.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);
}

Cada classe que vol observar alguna propietat necessita una llista d'observadors tipus PropertyChangeSupport

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);
        }
    }
}
Exemple de Observer

designpatterns-exemples_observer.zip

patrons_disseny.txt · Darrera modificació: 2022/11/24 08:20 per albert_palacios_jimenez