Patterns Ambito Cos`è un Design Pattern Descrizione di
Transcript
Patterns Ambito Cos`è un Design Pattern Descrizione di
Ambito ✘ Patterns lo sviluppo di sistemi con le tecnologie Object Oriented passa attraverso tre fasi interlacciate – analisi – design – implementazione Andrea Bottino Dip. Automatica e Informatica Politecnico di Torino 02/03/13 Andrea Bottino ✘ 1 Cos’è un Design Pattern sviluppo nell’ottica del riutilizzo (librerie, Design for reuse, Analisys for reuse) 02/03/13 Andrea Bottino Descrizione di un Design Pattern “Each pattern describes a Problem which occurs over and over in our environment (Context), and then describes the core of the Solution to that problem, in such a way that you can use this solution a million times over, without ever doing in the same way twice” Nome del Pattern Problema Soluzione (Christopher Alexander) 02/03/13 Andrea Bottino 2 Conseguenze 3 02/03/13 Andrea Bottino 4 views Smalltalk MVC ✘ terna di classi Model/View/Control in Smalltalk80 window a x 60 y 50 z 80 – Model: l’oggetto dell’applicazione – View: la sua rappresentazione su schermo – Control: definisce il modo in cui la vista reagisce all’input esterno (interazione con il mouse o con la tastiera) ✘ window b 30 30 10 c 10 20 10 window b a a b c c a = 50% b = 30% c = 20% prima di MVC i tre oggetti erano incapsulati in un’unica entità Model 02/03/13 Andrea Bottino 5 02/03/13 Andrea Bottino 6 ✘ ✘ ✘ ✘ applicabile a problemi più generali in tutti i casi in cui è necessario disaccoppiare gli oggetti, in modo che i cambiamenti di uno siano riflessi sugli altri gli oggetti non sono obbligati a conoscere i dettagli gli uni degli altri in MVC le viste possono essere composite utilizzando il concetto di Controller è possibile modificare in modo flessibile il tipo di risposta agli input esterni creando una gerarchia di Controller specializzati 02/03/13 ✘ Andrea Bottino 7 ✘ ✘ tipo – denota una particolare interfaccia (le interfacce hanno una gerarchia di ereditarietà) 02/03/13 – il dynamic binding permette di interscambiare oggetti aventi la stessa interfaccia a run-time. Questo permette all’oggetto client di fare pochissime assunzioni sull’oggetto che fornirà il servizio richiesto (supporto dell’interfaccia richiesta) ✘ ✘ ✔ ✔ – insiemi di classi predefinite utilizzate dall’applicazione. Forniscono funzionalità specifiche general-purpose (librerie di classi) e devono essere rese indipendenti dal dominio del problema (ignoto al momento della progettazione) Andrea Bottino ✘ framework – insieme di classi cooperanti che definiscono un design riutilizzabile per uno specifico problema 9 02/03/13 Andrea Bottino Andrea Bottino 10 Abstract Factory astraggono il processo di creazione degli oggetti e isolano il sistema da come gli oggetti sono creati, composti e rappresentati permettono grande flessibilità su cosa viene creato, da chi e quando Abstract factory Singleton 02/03/13 8 toolkit Creational Pattern ✘ Andrea Bottino Pattern, Toolkit, Framework polimorfismo 02/03/13 interfaccia dell’oggetto – insieme di metodi offerti da un oggetto; caratterizza l’insieme completo delle richieste (messaggi) che è possibile inviare all’oggetto. In OO un oggetto è noto solo attraverso la sua interfaccia dynamic binding – associazione a run-time di una richiesta ad un oggetto specifico. Diversi oggetti che forniscono le medesime operazioni possono avere diverse implementazioni della routine che serve la richiesta ✘ Concetti base 11 ✘ Scopo – fornire interfaccia per creare famiglie di oggetti dipendenti o collegati tra di loro senza doverne specificare le classi concrete ✘ Motivazioni – GUI toolkit che supportano diversi standard look and feel (Motif, Presentation Manager, Window) per la definizione di forme e comportamenti diversi per i vari “widget” (scrollbar, bottoni, finestre...) 02/03/13 Andrea Bottino 12 – istanziare elementi all’interno del codice significa ridurre la possibilita di modifiche al look and feel – si definisce una widget factory astratta che definisce un’interfaccia per creare i widget base – per ogni widget base viene definita un’interfaccia astratta – le sottoclassi concrete implementano i widget per lo specifico standard – i client chiamano le operazioni della widget factory per avere gli elementi concreti 02/03/13 Andrea Bottino 13 WidgetFactory Client CreateScrollBar() CreateWindow() Window PMWindow PMFactory MotifWindow MotifFactory CreateScrollBar() CreateWindow() CreateScrollBar() CreateWindow() Scrollbar PMScrollbar 02/03/13 MotifScrollbar Andrea Bottino 14 AbstractFactory ✘ Campi di utilizzo Client CreateProductA() CreateProductB() – sistemi indipendenti da come gli oggetti sono creati, composti e rappresentati – sistemi configurabili con piú famiglie di prodotti – rappresentazione astratta (attraverso le interfacce) di elementi di un toolkit AbstractProductA ProductA2 ConcreteFactoryA CreateProductA() CreateProductB() CreateProductA() CreateProductB() AbstractProductB ProductB2 02/03/13 ✘ Andrea Bottino 15 ProductA1 ConcreteFactoryB 02/03/13 Andrea Bottino ProductB1 16 Partecipanti – AbstractFactory (WidgetFactory): dichiara l’interfaccia con le operazioni per creare “prodotti” astratti – ConcreteFactory (MotifWidgetFactory): implementa le operazioni per creare gli oggetti concreti – AbstractProduct (Window): dichiara un’interfaccia per un tipo astratto di prodotti – ConcreteProduct (MotifWindow): prodotti concreti che implementano l’interfaccia specifica – Client: usa solo le interfacce di AbstractFactory e AbstractProduct 02/03/13 Andrea Bottino 17 ✘ Conseguenze + isola il cliente dall’implementazione delle classi concrete + permette facilmente di cambiare famiglia di prodotti + promuove la consistenza tra diverse famiglie di prodotti (standardizzazione dei prodotti) – è difficile supportare nuovi tipi di prodotti 02/03/13 Andrea Bottino 18 ✘ Singleton Implementazione – le factory sono Singleton (istanze uniche) ✘ Altri esempi ✘ – costruzione di labirinti Scopo – assicura che una classe abbia una sola istanza e fornisce un punto globale di accesso ad essa ✘ Motivazioni – esistono classi che devono essere uniche ▼ ▼ ▼ ▼ 02/03/13 Andrea Bottino 19 02/03/13 ✘ 02/03/13 ✘ return uniqueInstace; Andrea Bottino Andrea Bottino 21 Implementazione Conseguenze 02/03/13 Andrea Bottino 22 // File Singleton.c // File Singleton.h Singleton* Singleton::_instance = NULL; class Singleton { public: static Singleton* Instance(); protected: Singleton(); private: static Singleton* _instance; } Singleton* Singleton::Instance() { if(_instance == NULL) _instance = new Singleton; 02/03/13 20 + accesso controllato all’istanza unica + riduzione del numero di variabili globali + permette il raffinamento delle operazioni (il singleton puó essere sottoclassato) + permette facilmente di gestire un numero limitato di istanze Singleton static Instance() SingletonOperation() GetSingletonData() static uniqueInstance singletonData printer spooler file system manager window manager sistemi di accounting Andrea Bottino return _instance; } 23 02/03/13 Andrea Bottino 24 ✘ Structural Pattern Campi di utilizzo – quando deve esistere una sola istanza della classe e questa deve essere accessibile da chi la usa da un punto noto – quando l’istanza unica deve poter essere estesa per ereditarietá senza che gli utenti ne siano a conoscenza ✘ ✘ ✔ ✔ ✔ 02/03/13 Andrea Bottino 25 02/03/13 Composite ✘ definiscono le modalità di composizione di classi semplici per creare strutture più grosse oppure strutture che offrano nuove funzionalità largo utilizzo dell'ereditarietà tra interfacce e della composizione di oggetti (es: coesistenza di librerie diverse) Composite Decorator Proxy Andrea Bottino 26 – classe astratta che rappresenti sia le classi primitive che i loro contenitori e dichiari sia le operazioni primitive che quelle per la gestione degli insiemi Scopi – comporre oggetti in strutture ad albero per rappresentare strutture tutto-parti – trattare in modo uniforme oggetti singoli e composti ✘ Motivazioni – nelle applicazioni grafiche gli elementi possono essere sia singoli che composti, ma l’applicazione li deve trattare in modo uniforme senza dover prima verificare il tipo dell’oggetto 02/03/13 Andrea Bottino 27 Graphic 02/03/13 ✘ Draw() Add(Graphic) Remove(Graphic) GetChildren(int) Andrea Bottino 28 Campi di utilizzo – rappresentazione di strutture tutto-parti – client che siano in grado di ignorare le differenze tra oggetti singoli e composti graphics Circle Line Text Draw() Draw() Draw() 02/03/13 Picture Draw() Add(Graphic) Remove(Graphic) GetChildren(int) Andrea Bottino forall g in graphics g->Draw() add g to graphics 29 02/03/13 Andrea Bottino 30 Client Component ✘ Operation() Add(Component) Remove(Component) GetChildren(int) – Component (Graphic): definisce l’interfaccia degli oggetti nella composizione e ne implementa il comportamento di default; definisce i metodi di accesso ai componenti figli – Leaf (Text): rappresenta gli oggetti singoli nella composizione – Composite (Picture): definisce il comportamento per gli oggetti con figli; implementa la gestione della collezione dei componenti – Client: controlla tutti gli oggetti attraverso l’interfaccia Component children Leaf Operation() 02/03/13 ✘ Composite Operation() Add(Component) Remove(Component) GetChildren(int) forall g in children g->Operation() Andrea Bottino 31 Conseguenze Partecipanti 02/03/13 ✘ + rende semplice il codice del client + facilita l’aggiunta di nuovi componenti senza dover modificare il client Andrea Bottino ▼ ▼ ▼ 32 Implementazione – occorre considerare diversi fattori ▼ – la facilità di aggiungere componenti rende altresì difficile restringere l’uso dei componenti stessi (ad es. un Composite composto solo da certe categorie di Component) 02/03/13 Andrea Bottino ▼ ▼ 33 Component deve implementare una lista di Components? spreco di memoria per le foglie; ne vale la pena solo se le foglie sono relativamente poche cancellazione dei componenti - è buona regola far sì che una Composite sia responsabile della cancellazione dei suoi stessi figli Struttura dati per la memorizzazione dei componenti - dipende dalle necessità di ordinamento dell’applicazione riferimenti espliciti ai genitori - permettono di semplificare l’attraversamento e la gestione della struttura. Il riferimento al genitore solitamente si inserisce nel Component ed è gestito dalle operazioni Add e Remove massimizzazione dell’interfaccia di Component vs. correttezza semantica - una classe dovrebbe definire solo le operazioni che hanno un senso per le sue sottoclassi (hanno tutte senso in Leaf?) dichiarazione delle operazioni di gestione dei figli - deve essere fatta in Component o in Composite (occorre scegliere tra trasparenza e sicurezza)? 02/03/13 Andrea Bottino 34 Decorator ✘ Scopo – aggiunge dinamicamente ad un oggetto nuove caratteristiche – offre una alternativa flessibile all’ereditarietà per l’estensione delle funzionalità ✘ Motivazioni – a volte si vogliono aggiungere capacità o responsabilità solo ad oggetti singoli e no ad intere classi (aggiungere un bordo e una scrollbar ad una componente di testo) 02/03/13 Andrea Bottino 35 02/03/13 Andrea Bottino 36 aScrollDecorator This is a text component Use for examples only – la soluzione è racchiudere il componente all’interno di un’altro oggetto che aggiunge il bordo. L’oggetto che incapsula è detto Decorator e si conforma all’interfaccia dell’oggetto che decora in modo che la sua presenza sia trasparente al Client del componente – il Decorator intercetta le richieste, le invia al componente e compie azioni aggiuntive – la trasparenza lascia includere più Decorator uno dentro l’altro 02/03/13 Andrea Bottino This is a text component Use for examples only Who needs to read? .. .. .. That’s all folks.... Who needs to read? .. .. .. That’s all folks.... aTextView aBorderDecorator aBorderDecorator component 37 02/03/13 aScrollDecorator component aTextView Andrea Bottino 38 VisualComponent Draw() ✘ TextView Decorator Draw() Draw() componet->Draw() BorderDecorator Draw() ScrollTo() Draw() DrawBorder() scrollPosition borderWidth 02/03/13 – aggiunta di proprietà agli oggetti in modo dinamico e trasparente senza intaccare altri oggetti – gestione di proprietà che possono essere rimosse dinamicamente – impraticabilità dell’estensione per ereditarietà (esplosione del numero di sottoclassi) component ScrollDecorator Campi di utilizzo Decorator::Draw(); DrawBorder(); Andrea Bottino 39 02/03/13 Andrea Bottino 40 Component Operation() ✘ ConcreteComponent Decorator Operation() Operation() ConcreteDecoratorA Operation() addedState 02/03/13 component componet->Operation() ConcreteDecoratorB Operation() AddedBehaviour() Andrea Bottino Decorator::Operation(); AddedBehaviour(); 41 Partecipanti – Component (VisualComponent): definisce l’interfaccia per gli oggetti a cui si possono aggiungere dinamicamente nuove caratteristiche – ConcreteComponent (TextView): definisce il componente concreto – Decorator: contiene un riferimento ad un Component e definisce un’interfaccia conforme a quella del componente stesso – ConcreteDecorator (BorderDecorator): aggiunge proprietà al componente 02/03/13 Andrea Bottino 42 ✘ Altri ✘ Conseguenze esempi – gestione di Stream + è più flessibile dell’ereditarietà (statica) + le caratteristiche degli oggetti possono essere modificate a run-time (attaccando e staccando i Decorator) + evita il problema di avere classi cariche di caratteristiche nella gerarchia Stream BufferFull() component – un Decorator e il suo Component non sono identici – generazione di molti piccoli oggetti FileStream MemoryStream StreamDecorator BufferFull() BufferFull() BufferFull() ASCII7Stream ConcreteDecoratorB BufferFull() 02/03/13 Andrea Bottino 43 Proxy 02/03/13 Andrea Bottino aTextDocument 44 anImageProxy fileName Scopi – fornisce una rappresentazione di un altro oggetto per controllare l’accesso all’oggetto stesso ✘ compress data in buffer; StreamDecorator::BufferFull(); BufferFull() image ✘ componet->BufferFull() in memoria anImage su disco Motivazioni – un motivo per controllare l’accesso ad un oggetto è quello di aggravare l’applicazione del costo della sua creazione solo al momento in cui l’oggetto stesso è strettamente necessario – editor di documenti contenente oggetti grafici 02/03/13 Andrea Bottino Graphic ✔ l’ImageProxy crea l’immagine in memoria solo quando l’editor chiede di visualizzarla (invocando il metodo Draw()) ✔ le chiamate successive vengono inviate direttamente all’oggetto Image 45 Draw() GetExtent() Store() Load() imageImp extent ✘ ImageProxy image Andrea Bottino Draw() GetExtent() Store() Load() fileName extent if(image == NULL){ image = LoadImage(fileName) } image->Draw(); Campi di utilizzo – Proxy è applicabile in ogni caso in cui sia necessario avere un riferimento più versatile di un semplice puntatore ▼ ▼ ▼ if(image == NULL){ return extent; } ▼ return image->GetExtent(); 02/03/13 46 DocumentEditor Draw() GetExtent() Store() Load() Image 02/03/13 Andrea Bottino 47 02/03/13 Remote Proxy: rappresentazione locale per un oggetto localizzato in un diverso spazio di indirizzamento (architetture Client-Server) Virtual Proxy: per oggetti la cui creazione è un proceso costoso (ImageProxy) Protection Proxy: permette di controllare l’accesso al riferimento (oggetti con diversi diritti di accesso) Smart Reference: alternativa al semplice puntatore che permette di eseguire operazioni aggiuntive (smart pointer) Andrea Bottino 48 ✘ Subject Client RealSubject Request() ... Proxy realSubject 02/03/13 ✘ Request() ... .... realSubject->Request(); .... Andrea Bottino 49 02/03/13 – overload degli operatori di accesso in C++ class Image; extern Image* LoadImageFile(const char* file); class ImagePtr { public: ImagePtr(const char* imageFile); virtual Image* operator->(); virtual Image& operator&(); private: Image* LoadImage(); Image* _image; const char* _imageFile; } ✘ Andrea Bottino 51 02/03/13 + l’indirizzamento attraverso il proxy comporta diversi vantaggi ▼ ▼ ▼ 02/03/13 50 Andrea Bottino 52 Behavioural Pattern Conseguenze ▼ Andrea Bottino ImagePtr::ImagePtr(const char* theImageFile) { _imageFile = theImageFile; _image = NULL; } Image* ImagePtr::LoadImage() { if(_image == NULL) _image = LoadImageFile(_imageFile); return _image; } Image* ImagePtr::operator->() { return LoadImage(); } Image& ImagePtr::operator*() { return *LoadImage(); } Implementazione 02/03/13 Partecipanti – Proxy (ImageProxy): mantiene un riferimento che permette di acceder all’oggetto reale, fornendo un’interfaccia identica all’oggetto stesso in modo da poter essere utilizzato al suo posto. Controlla l’accesso all’oggetto ed è responsabile della sua creazione e della sua distruzione – Subject (Graphic): definisce l’interfaccia comune per l’oggetto e per il suo Proxy – RealSubject (Image): definisce l’oggetto reale rappresentato dal Proxy Request() ... ✘ può nascondere il fatto che l’oggetto non appartiene ad un diverso spazio di indirizzamento può essere utilizzato per l’ottimizzazione dell’applicazione (creation on demand) può fornire strumenti aggiuntivi di protezione degli oggetti permette di implementare il copy on write (il salvataggio o la copia di oggetti complessi viene effettuta solo se a questi sono stati fatti accessi in scrittura) Andrea Bottino 53 ✔ ✔ ✔ caratterizzano il modo in cui classi/oggetti interagiscono e distribuiscono le loro responsabilità Command Iterator Observer 02/03/13 Andrea Bottino 54 Command ✘ – Command permette di creare richieste per oggetti non specifici trasformando le richieste in oggetti che possono essere memorizzati e/o passati come parametri tra i vari oggetti dell’applicazione – la chiave è una classe astratta Command che dichiara un’interfaccia per l’esecuzione di operazioni Scopo – incapsulare una richiesta in un oggetto in modo da poter definire dei Client in grado di accettare diverse richieste e permettere di “disfare” le operazioni ✘ Motivazioni – a volte è necessario inviare delle richieste a degli oggetti senza avere alcuna informazione sull’oggetto a cui deve essere inviata la richiesta o sul tipo di richiesta stessa – bottoni, menu, ... in librerie GUI 02/03/13 Andrea Bottino 55 02/03/13 Andrea Bottino 56 Command Execute() Application Menu MenuItem command Command Add(document) Add(MenuItem) Clicked() Execute() Open() Close() Cut() Copy() Paste() command->execute() document PasteCommand Execute() document->Paste() Command – Application configura ogni MenuItem con un’istanza di un comando concreto; quando l’utente seleziona un item, il MenuItem chiama Execute() del Command che porta a termine l’operazione – i MenuItem non conoscono la sottoclasse di Command che stanno utilizzando 02/03/13 Document Open() Close() Cut() Copy() Paste() Document Andrea Bottino 57 Execute() Application application Add(document) OpenCommand name = AskUser() doc = new Document(name) application->add(doc) doc->Open() Execute() AskUser() 02/03/13 Andrea Bottino 58 Command Execute() ✘ Struttura commands Command MacroCommand Execute() ✘ Client Conseguenze + disaccoppiamento tra l’oggetto che invoca l’operazione da quello che la deve eseguire + si possono rimpiazzare dinamicamente i comandi (utilizzo di menù sensibili al contesto) 02/03/13 Invoker Execute() for all c in commands c->Execute() Andrea Bottino 59 Receiver ConcreteCommand Action() Execute() state command receiver->Action() 02/03/13 Andrea Bottino 60 ✘ Iterator Applicabilità – parametrizzare gli oggetti secondo la funzione che devono svolgere (ad es. MenuItem) – supportare l’undo: la Execute di Command può registrare la sequenza di comandi che vengono eseguiti. Occorre supportare un’operazione Unexecute() – supporto per le transizioni in sistemi complessi (una transizione è un insieme di cambiamenti sui dati) che possono essere modellate tramite Command 02/03/13 Andrea Bottino List 61 list Count() ... Append(Element) Remove(Element) CreateIterator() ... ✘ Scopo – accedere in modo sequenziale oggetti aggregati senza rendere pubblica la struttura dell’aggregazione ✘ Motivazioni – un’aggregazione di oggetti (come una lista o un insieme) deve fornire un modo per accedere ai suoi elementi indipendentemente dalla sua struttura – fornire diversi metodi di visita dell’insieme stesso senza fornire diverse operazioni di visita 02/03/13 ✘ First() Next() IsDone() CurrentItem() Aggregate Iterator CreateIterator() First() Next() IsDone() CurrentItem() index Andrea Bottino ConcreteAggregate return new ConcreteIterator(this); 63 02/03/13 ✘ – Iterator: definisce l’interfaccia attraverso cui accedere agli elementi della lista – ConcreteIterator: implementa l’interfaccia di Iterator; mantiene traccia della posizione corrente nell’attraversamento dell’insieme – Aggregate: definisce l’interfaccia per un generico insieme di dati – ConcreteAggregate: implementa l’interfaccia di creazione dell’iteratore per generare un’istanza di iteratore specifico Andrea Bottino ConcreteIterator CreateIterator() Partecipanti 02/03/13 62 ListIterator – tramite il ListIterator si possono accedere gli elementi della lista in modo sequenziale – la lista deve essere responsabile per la creazione del proprio iteratore; in questo modo ogni tipo diverso di ista può creare il suo specifico iteratore 02/03/13 Andrea Bottino Andrea Bottino 64 Conseguenze + permette di definire modalità diverse di attraversamento dell’insieme fornendo un supporto comune + gli iteratori semplificano l’interfaccia dell’aggregato, in quanto evitano di inserire le stesse operazioni all’interno della classe List + su di una lista possono esistere più di un iteratore attivo, in quanto gli iteratori mantengono al loro interno lo stato dell’attraversamento 65 02/03/13 Andrea Bottino 66 ✘ template <class T> class CSetIterator { ... public: void first(); void next(); int done(); T getElement(); }; int somma(CSet<int> *set){ int sum = 0; CSetIterator<int> *i = set->createIterator(); for(i->first();!i->done();i->next()) sum += i->getElement(); delete i; return sum; } Implementazione template <class T> class CSetIterator; template <class T> class CSet { ... public: void add(T elem); void remove(T elem); int contains(T elem); CSetIterator<T> *createIterator(); }; 02/03/13 Andrea Bottino 67 Observer ✘ Scopo – definire un sistema di interdipendenza tra gli oggetti in modo che i cambiamenti dello stato di un oggetto siano notificati e riflessi in tutti gli oggetti che dipendono da lui ✘ 02/03/13 Andrea Bottino 68 – classi strattamente legate riducono le possibilità di riutilizzo – MVC in Smalltalk – un soggetto può avere un numero qualsiasi di osservatori che vengono notificati dal soggetto in seguito ad un cambiamento dello stato; in risposta ogni osservatore interroga il soggetto per conoscerne il nuovo stato Motivazioni – dividere un sistema in un insieme di classi cooperanti crea il problema di mantenere la consistenza tra gli oggetti in relazione 02/03/13 Andrea Bottino 69 02/03/13 Andrea Bottino Subject observers 70 observers window a x 60 y 50 z 80 window b 30 30 10 c 10 20 10 window Attach(Observer) Detach(Observer) Notify() b a a b c c for all o in observers o->Update() ConcreteSubject notifiche di cambiamenti richieste, modifiche GetState() subjectState a = 50% b = 30% c = 20% Client Update() ConcreteObserver subject Update() observerState return subjectState observerState = subject->getState() observable 02/03/13 Andrea Bottino 71 02/03/13 Andrea Bottino 72 ✘ Partecipanti ✘ – Subject: ▼ ▼ conosce i suoi osservatori; un numero qualsiasi di osservatori può osservare il soggetto fornisce l’interfaccia per agganciare e rimuovere gli osservatori – Observer: definisce l’interfaccia per gli oggetti a cui devono essere notificati i cambiamenti del soggetto – ConcreteSubject: salva lo stato di interesse e notifica i suoi osservatori quando lo stato viene modificato – ConcreteObserver: mantiene un riferimento al soggetto (ConcreteSubject) e implementa l’interfaccia di Update per mantenere il suo stato coerente con quello del sogg. 02/03/13 Andrea Bottino 73 Bibliografia ✔ ✔ ✔ C. Alexander, S. Ishikawa, M Silverstein, M. Jacobson, et al., “A Pattern Language”, Oxford University Press, 1977 J. O. Coplien, “Advanced C++ Programming Styles and Idioms”, Addison-Wesley, Reading, MA, 1992 E. Gamma, R. Helm, R. Johnson, J. Vlissides, “Design Patterns. Elements or Reusable Object-Oriented Software”, Addison-Wesley Publishing Company, 1994 02/03/13 Andrea Bottino 75 Conseguenze + permette di modificare in maniera indipendente i soggetti e gli osservatori + astrae l’accoppiamento tra Subject e Observer + supporto per comunicazioni di tipo broadcast – Updated non previsti (una piccola modifica nel soggetto può provocare una cascata di notifiche e update 02/03/13 Andrea Bottino 74