Design Patterns Luca Lista L.Lista Design Patterns E. Gamma et al., Design Patterns “Elementi di software OO riutilizzabile” • Piccoli insiemi di classi che collaborano implementando dei comportamenti tipici – Creational patterns – Structural patterns – Behavioral patterns Alcuni pattern classici stanno diventanto obsoleti grazie al supporto dei Template L.Lista Factory Client Factory AbstractProduct createProduct1 () : AbstractProduct createProduct2 () : AbstractProduct I client possono richiedere la creazione di un prodotto senza dipendervi. La Factory dipende dai prodotti concreti, mentre i client dipendono solo AbstractProduct. ConcreteProduct1 L.Lista ConcreteProduct2 Singleton _instance : Singleton instance () : Singleton specificService () Singleton if (_instance==0) _instance = new Singleton(); return _instance; user_code() { Singleton::instance()->specificService(...); } Il Singleton pattern piò essere usato ogni volta che una classe deve essere instanziata una sola volta, e viene usata da diversi oggetti. Per evitare istanziazione accidentale, il constructor deve essere privato. Più istanze, ma in numero ben determinato, possono esistere (multiton) Siccome vengono usate funzioni statiche, l’ereditarietà non può essere applicata. L.Lista Proxy Subject Client reques t( ) Proxy RealSubject _sub ject _s ubject : RealSubject reques t( ) 1 Una richiesta da un client a un server, può essere mediata dal Proxy, che può compiere anche altre operazioni (I/O, caching, etc.) L.Lista reques t( ) ... _s ubject->reques t(); ... Composite Client Il client può trattare componenti e compositi usando la stessa interfaccia. La composizione può essere ricorsiva. Com ponent operation( ) 1..* _children Com pos ite operation( ) Leaf operation( ) Esempio: programmi di grafica vettoriale for c in all _children c->operation(); L.Lista Composite Shape Client Il client può trattare componenti e compositi usando la stessa interfaccia. La composizione può essere ricorsiva. Shape draw( ) 1..* _children Gruppo draw( ) Cerchio, Rettangolo, ... draw( ) Esempio: programmi di grafica vettoriale for c in all _children c->draw(); L.Lista Strategy Il pattern Strategy permette di scegliere l’algoritmo da eseguire a run-time. { ... Strategy* s ; s ->doAlgorithm(); ... Nuovi algoritmo possono essere introdotti senza modificare i client. } Strategy Client doAlgorithm( ) ConcreteStrategyA doAlgorithm( ) ConcreteStrategyB doAlgorithm( ) L.Lista ConcreteStrategyC doAlgorithm( ) Observer Subject Observer _ob servers update( ) _observers : Observer attach (Observer) notify () 0..* for all o in _ observables o->update(); ConcreteObserver ConcreteSubject _status : Status status( ) return _status; _sub ject Lo stato dell’Observer dipende dallo stato del Subject. Il Subject notifica a tutti gli Observer registrati che il suo stato è cambiato. L.Lista _status : Status _subject . ConcreteSubject update( ) _status = _subject->status(); Template Method AbstractClass ... primitiveOperation1(); ... primitiveOperation2(); ... tem plateMethod( ) primitiveOperation1( ) primitiveOperation2( ) Un Template Method è un modo di garantire un comportamento comune. ConcreteClass primitiveOperation1( ) primitiveOperation2( ) Le operazioni elementari sono delegate alle sottoclassi. L.Lista Visitor Client Vis itor vis it1 (ConcreteElem ent1) vis it2 (ConcreteElem ent2) Elem ent accept (Vis itor) ConcreteVisitor1 vis it1 (ConcreteElem ent1) vis it2 (ConcreteElem ent2) ConcreteElem ent1 ConcreteElem ent2 accept (Vis itor v) accept (Vis itor v) v->vis it1(this ) v->vis it2(this ) ConcreteVisitor2 vis it1 (ConcreteElem ent1) vis it2 (ConcreteElem ent2) Permette di aggiungere nuove operazioni a Element senza modificarne l’interfaccia. Per aggiungere nuovi ConcreteElement, bisogna modificare tutti i Visitors. L.Lista Visitor main Visitor calcolaCerchio (const Cerchio&) : double calcolaRettangolo (const Rettangolo&) : double Shape accept (Visitor&) const : double Area Perimetro calcolaCerchio (const Cerchio&) : double calcolaCerchio (const Cerchio&) : d calcolaRettangolo (const Rettangolo&) : doublecalcolaRettangolo (const Rettangol Rettangolo Cerchio accept (Visitor& v) const : double accept (Visitor& v) const : double v.calcolaRettangolo(*this) v.calcolaCerchio(*this) L.Lista