Progetto

Generale

Profilo

DesignPattern » Cronologia » Versione 9

Amministratore Truelite, 27-02-2007 16:14

1 9 Amministratore Truelite
2
h2. Singleton Pattern
3
4 5 Amministratore Truelite
Il pattern singleton viene utilizzato quando si vuole creare una sola instanza di una classe. 
5
6
Proviamo a pensare al caso di parsing di dati; essendo questa una operazione lunga e dispendiosa in termini di calcolo vogliamo poter riutilizzare i risultati della prima "esecuzione".
7 1 Amministratore Truelite
8
Ecco un esempio:
9 9 Amministratore Truelite
<pre>
10 5 Amministratore Truelite
# Singleton class
11 9 Amministratore Truelite
# If instance is null creates an instance calling +new+ from object
12 1 Amministratore Truelite
class Singleton(object):
13 5 Amministratore Truelite
        instance = None
14
                
15 9 Amministratore Truelite
        def +new+(cls):
16 5 Amministratore Truelite
                if cls.instance == None:
17 9 Amministratore Truelite
                        cls.instance = super(Singleton, cls).+new+(cls)
18 5 Amministratore Truelite
                return cls.instance
19
20
a = Singleton()
21
22
print type(a)
23 1 Amministratore Truelite
print id(a)
24 5 Amministratore Truelite
25
26 1 Amministratore Truelite
b = Singleton()
27 5 Amministratore Truelite
print type(b)
28
print id(b)
29 9 Amministratore Truelite
</pre>
30 5 Amministratore Truelite
31
Risultato esecuzione:
32
33 9 Amministratore Truelite
<class '+main+.Singleton'> 
34 1 Amministratore Truelite
35
-1211002548
36
37 9 Amministratore Truelite
<class '+main+.Singleton'>
38 5 Amministratore Truelite
39
-1211002548
40
41 1 Amministratore Truelite
42
43 9 Amministratore Truelite
h2. Flyweight Pattern
44
45
46 1 Amministratore Truelite
Il pattern flyweight viene utilizzato quando si ha a che fare con un gran numero di oggetti con alcune caratteristiche comuni (che variano raramente) ed altre non comuni di cui ogni oggetto si fa carico per se.
47
48
Questo pattern può essere molto utile quando si vuole alleggerire il carico in ram di un grande numero di oggetti, facendo in modo di riutilizzare oggetti con "lo stesso stato".
49
50
Ecco un esempio di codice:
51 9 Amministratore Truelite
<pre>
52 2 Amministratore Truelite
# Flyweight pattern
53 1 Amministratore Truelite
# La classe "TipoOggetto" mantiene informazione delle caratteristiche intrinseche degli oggetti (in comune)
54 9 Amministratore Truelite
class [[TipoOggetto]](object):
55 1 Amministratore Truelite
        _listaOggetti = {}
56
        
57 9 Amministratore Truelite
        def +new+(cls, name):
58
                oggetto = [[TipoOggetto]]._listaOggetti.get(name,None)
59 1 Amministratore Truelite
                
60
                if not oggetto:
61 9 Amministratore Truelite
                        oggetto = object.+new+(cls)
62
                        [[TipoOggetto]]._listaOggetti[name] = oggetto
63 1 Amministratore Truelite
                return oggetto
64
65
66 9 Amministratore Truelite
        def +init+(self, name):
67 2 Amministratore Truelite
                self.name = name
68
                print id(self), name
69
70
# Per mostrare come un oggetto può avere delle caratteristiche estrinseche si deve creare
71 1 Amministratore Truelite
# un'altra classe che utilizzi due oggetti di cui uno di tipo "TipoOggetto"
72
73 9 Amministratore Truelite
class [[ProvaFlyweight]]:
74 2 Amministratore Truelite
        
75 9 Amministratore Truelite
        def +init+(self, name, altro):
76
                self.name = [[TipoOggetto]](name)
77 2 Amministratore Truelite
                self.altro = altro
78
79
80 9 Amministratore Truelite
a = [[ProvaFlyweight]]("obj1", "1")
81
b = [[ProvaFlyweight]]("obj2", "2")
82
c = [[ProvaFlyweight]]("obj3", "3")
83
d = [[ProvaFlyweight]]("obj1", "4")
84 2 Amministratore Truelite
85
print id(a.name)
86
print id(b.name)
87
print id(c.name)
88
print id(d.name)
89
90
91
print id(a.altro)
92
print id(b.altro)
93
print id(c.altro)
94 1 Amministratore Truelite
print id(d.altro)
95
96 9 Amministratore Truelite
</pre>
97 1 Amministratore Truelite
-1210465204 obj1
98 3 Amministratore Truelite
99 1 Amministratore Truelite
-1210465140 obj2
100
101
-1210465076 obj3
102
103
-1210465204 obj1
104 3 Amministratore Truelite
105
-1210465204
106
107 1 Amministratore Truelite
-1210465140
108
109 3 Amministratore Truelite
-1210465076
110 1 Amministratore Truelite
111
-1210465204
112 3 Amministratore Truelite
113
-1210102464
114 1 Amministratore Truelite
115 3 Amministratore Truelite
-1210465600
116
117 1 Amministratore Truelite
-1210465536
118 3 Amministratore Truelite
119 1 Amministratore Truelite
-1210465440
120 4 Amministratore Truelite
121 6 Amministratore Truelite
Come si può vedere dal risultato dell'esecuzione l'attributo "name" dell'instanza "a" e "d" sono un unico oggetto.
122
123
124 9 Amministratore Truelite
h2. Observer Pattern
125
126
127 6 Amministratore Truelite
Il pattern Observer definisce una dipendenza "uno a molti" tra oggetti. In questo pattern gli oggetti rivestono due ruoli: 
128
129 9 Amministratore Truelite
* Subject (il soggetto)
130
* Listeners (gli oggetti che ascoltano il soggetto)
131 6 Amministratore Truelite
132
I listeners (o observer) si mettono in ascolto del soggetto; quando il soggetto "cambia stato" allora aggiorna tutti i listener in ascolto (registrati) su di lui. Questo paradigma di programmazione è quello che in alcuni linguaggi si trova nativo, ed è chiamato programmazione ad eventi.
133
134
Ecco un esempio:
135 9 Amministratore Truelite
<pre>
136 6 Amministratore Truelite
class Subject:
137 9 Amministratore Truelite
        +listeners = []
138 6 Amministratore Truelite
139 1 Amministratore Truelite
        def register(self, listener):
140 9 Amministratore Truelite
                self.+listeners.append(listener)
141 1 Amministratore Truelite
142 9 Amministratore Truelite
        def +notifyAll(self):
143
                for entry in self.+listeners:
144 6 Amministratore Truelite
                        entry.notify()
145
146 1 Amministratore Truelite
        def statusChanged(self):
147 9 Amministratore Truelite
                self.+notifyAll()
148 6 Amministratore Truelite
149
class Listener:
150 1 Amministratore Truelite
        
151 9 Amministratore Truelite
        def +init+(self, listenerName):
152 6 Amministratore Truelite
                self.name = listenerName
153
154
        def notify(self):
155
                print "Notify on listener ", self.name
156 1 Amministratore Truelite
157
s = Subject()
158 6 Amministratore Truelite
159
l1 = Listener("1")
160
l2 = Listener("2")
161
l3 = Listener("3")
162
l4 = Listener("4")
163
l5 = Listener("5")
164
165
166
s.register(l1)
167
s.register(l2)
168
s.register(l3)
169
s.register(l4)
170
s.register(l5)
171
172
s.statusChanged()
173
174 9 Amministratore Truelite
</pre>
175 7 Amministratore Truelite
176 8 Amministratore Truelite
177 9 Amministratore Truelite
h2. Decorator Pattern
178
179
180 8 Amministratore Truelite
E' un pattern abbastanza semplice che è parte fondamentale dell'OOP. Serve per aggiungere funzionalità agli oggetti.
181
182
Vediamo un esempio:
183 9 Amministratore Truelite
<pre>
184 8 Amministratore Truelite
class A:
185 9 Amministratore Truelite
        def +init+(self, b):
186 8 Amministratore Truelite
            """ b è una istanza della classe B"""
187
            self.b = b
188
189 9 Amministratore Truelite
        def +getattr+(self, name):
190 8 Amministratore Truelite
            """ I metodi/attributi di A non devono conoscere come sono delegati a b """
191
            return getattr(self.b, name)
192
193
194
b = B()
195
a = A(b)
196 9 Amministratore Truelite
</pre>
197 1 Amministratore Truelite
198 9 Amministratore Truelite
Il metodo +getaddr+ viene chiamato quando non vengono trovati gli attributi, quindi in automatico si vanno a ricercare nella 
199 1 Amministratore Truelite
classe B, senza dovere distinguere le cose.