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