Pattern GOF 2
Transcript
Pattern GOF 2
Pattern GOF 2 Laboratorio di Ingegneria del Software Andrea Bei Pattern Strutturali Nome Adapter Bridge Descrizione Permette a una classe di supportare un'interfaccia anche quando la classe non implementa direttamente quell'interfaccia. Disaccoppia un’astrazione dalla sua implementazione in modo che possano variare in modo indipendente. Composite Serve a rappresentare un oggetto complesso in una struttura con relazione di contenimento. (esempio gerarchie di contenimento nelle interfacce grafiche) Decorator Aggiunge nuove responsabilità ad un oggetto in modo dinamico, è un alternativa alle sottoclassi per estendere le funzionalità. (In Java è ampiamente utilizzato negli stream) Facade Fornisce un'unica interfaccia di accesso a un sistema complesso evitando le dipendenze sulla struttura interna del sistema. Flyweight Permette di condividere oggetti qualora un loro numero elevato avrebbe costi proibitivi di efficienza e gestione. Proxy Provvede un surrogato di un oggetto per controllarne gli accessi 2 Composite Problema Come trattare un gruppo o una struttura composta di oggetti nello stesso modo (polimorficamente) di un oggetto non composto (atomico) ? Soluzione Si definiscano le classi degli oggetti composti (Composite) e atomici (Leaf) in modo che implementino la stessa interfaccia (Component) 3 Composite esempio Problema Come gestire più politiche di prezzo su uno stesso cliente ? es: { ... return pricingStrategy.getTotal( this ) } Component Sale date ... 10 % sconto per anziani 50 % di sconto per vendite superiori di 500 dollari .... 1 Leaf Leaf PercentageDiscount PricingStrategy AbsoluteDiscount OverThreshold PricingStrategy 1..* strategies Composite Composite PricingStrategy percentage : float getTotal( Sale ) : Money Soluzione Si definisca una Composite di Strategy Si definiscano due sottoclassi di questa che applicano due strategie composte «interface» ISalePricingStrategy pricingStrategy getTotal( Sale ) : Money getTotal() ... Si possono gestire in modo che sia conveniente per il cliente o per il negoziante La Composite All composites maintain a list of mantiene laTherefore, lista contained strategies. define a common superclass delle Strategie (una CompositePricingStrategy that lista dilistoggetti defines this (named strategies). Component) discount : Money threshold : Money add( ISalePricingStrategy ) getTotal( Sale ) : Money getTotal( Sale ) : Money la migliore per il cliente la migliore per il negoziante { return sale.getPreDiscountTotal() * percentage } CompositeBestForCustomer PricingStrategy getTotal( Sale ) : Money { lowestTotal = INTEGER.MAX for each ISalePricingStrategy strat in pricingStrategies { total := strat.getTotal( sale ) lowestTotal = min( total, lowestTotal ) } return lowestTotal } CompositeBestForStore PricingStrategy getTotal( Sale ) : Money 4 Bridge Problema: come separare un’astrazione dalla sua implementazione, in modo che entrambe possano variare indipendentemente. Soluzione:separare l’astrazione dall’implementazione legando oggetti della seconda a quelli della prima, tramite un relazione di aggregazione. 5 Bridge (esempio) L’astrazione Matrix ha due implementazioni: 1. come matrice sparsa (contenente solo i valori diversi da 0) 2. come matrice completa Una Matrix può essere implementata con una Collection (un’altra astrazione) che può essere a sua volta implementata con 1. Vector o 2. ArrayList 6 Bridge Schema del Pattern 7 Bridge 8 Decorator Problema:come aggiungere dinamicamente responsabilità ad un oggetto ? Soluzione: si creino delle classi wrapper (Decorator) che racchiudono (decorano) gli oggetti ai quali si vuole aggiungere le nuove responsabilità. Oggetti “decorati”” e wrapper devono implementare una interfaccia comune, in modo che l’applicazione possa continuare ad interagire con gli oggetti decorati attraverso l’interfaccia comune sia possibile l’applicazione di un Decorator ad un altro oggetto già decorato, ottenendo in questo modo la sovrapposizione di più responsabilità. Obj Decorator 1 Decorator 2 Es: • Decorator e oggetti da decorare implementano la stessa interfaccia in cui è definito il metodo m1 • Ogni “decorazione” aggiunge responsabilità al metodo m1 definito in obj • Il metodo m1 di ogni decorator racchiude la logica del decorator stesso ed infine invoca il metodo m1 del decorator contenuto fino ad arrivare all’oggetto OBJ 9 Decorator: esempio Problema: una azienda è costituita da Employee che afferiscono ad uffici di appartenenza un Engineer è un tipo di Employee un Engineer può assumere l’incarico di capoufficio (AdministrativeManger) o di capoprogetto (ProjectManager) un Engineer può essere capoufficio ed anche capoprogetto di più progetti L’interfaccia comune serve a garantire la relazione di aggregazione La classe concreta di base •Le classi di tipo ResponsibleWorker (AdministrativeManager e ProjectManager) sono i Decorator •Engineer può essere “decorato” con diverse responsabilità ovvero con diverse classi di tipo ResponsibleWorker 10 Decorator Schema del pattern 11 Decorator 12 Decorator "D.O.S.- Doors Operating System" “EveryoneLoggedTo Internet Explorer" Engineer AdministrativeManager ProjectManager ProjectManager 13 Facade Problema:come fornire una interfaccia unificata per un insieme di interfacce di un sottosistema, rendendo più facile l’uso di quest’ultimo. Soluzione: si crei una classe Facade che mostri una interfaccia semplificata al cliente e si faccia carico di gestire le complessità delle iterazioni tra le interfacce e le classi del sottosistema E’ usato nel pattern architetturale layers Schema del pattern // Layer 1 class Object1Layer1 {} class Object2Layer1 {} ... class ObjectNLayer1 {} interface FacadeLayer1 { public void method() { // use ObjectNLayer1 } } // Layer 2 class ObjectNLayer2 { facadeLayer1.method(); } 14 Facade (esempio) Problema: in Java per prendere un input dalla tastiera è necessario scrivere il codice seguente. Come semplificare questa operazione ? Come evitare che il programmatore sia costretto a gestire BufferedReader, InputStreamReader, System, String, Integer, Double, Float, ecc. Soluzione: Creare una classe Facade ConsoleReader che offre una interfaccia semplice con le operazioni getString, getInteger, getDouble e nasconde al cliente le chiamate alle classi di cui sopra 15 Facade 16 Flyweight Problema:come gestire un numero elevato di oggetti dello stesso tipo in modo efficiente in termini di memoria Soluzione: si creino dei “flyweight” ovvero degli oggetti condivisi che possono essere utilizzati in diversi contesti contemporaneamente, in quanto in questi contesti condividono lo stato interno, e quello che non è interno si può esternalizzare. Esempio: Un sistema di controllo deve gestire in tempo reale una coda di eventi (Event). Gli eventi, rappresentati come oggetti, devono essere analizzati da un controllore, che deve reagire opportunamente a seconda dell’evento Senza FlyWeight Con FlyWeight 17 Flyweight (esempio) 18 Flyweight Schema del Pattern 19 Proxy Problema: come introdurre un surrogato, o rappresentante di un oggetto. Ad esempio quando l’accesso all’oggetto richiede tempo (è computazionalmente pesante) e si vogliono implementare politiche di caching Soluzione:si implementi una classe Proxy che offra la stessa interfaccia della classe originale e che sia in grado di risolvere le richieste più “semplici”. Solo le richieste più complesse vengono inoltrate alla classe originale 20 Proxy Esempio: FileHandler (gestisce operazioni su un file di testo) Proxy: il proxy fa un caching dell’ultima riga acceduta Inefficienza: per accedere ad una riga del file occorre scandire tutto il file fino alla riga voluta anche se la riga è stata acceduta nella richiesta precedente 21 Proxy Schema del Pattern 22 Proxy 23