Progetto

Generale

Profilo

DesignPattern » Cronologia » Versione 8

Amministratore Truelite, 27-02-2007 16:14

1 5 Amministratore Truelite
== Singleton Pattern ==
2
Il pattern singleton viene utilizzato quando si vuole creare una sola instanza di una classe. 
3
4
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".
5
6
Ecco un esempio:
7
{{{
8
# Singleton class
9
# If instance is null creates an instance calling __new__ from object
10
class Singleton(object):
11
        instance = None
12
                
13
        def __new__(cls):
14
                if cls.instance == None:
15
                        cls.instance = super(Singleton, cls).__new__(cls)
16
                return cls.instance
17
18
a = Singleton()
19
20
print type(a)
21
print id(a)
22
23
24
b = Singleton()
25
print type(b)
26
print id(b)
27
}}}
28
29
Risultato esecuzione:
30
31
<class '__main__.Singleton'> 
32
33
-1211002548
34
35
<class '__main__.Singleton'>
36
37
-1211002548
38
39
40 1 Amministratore Truelite
== Flyweight Pattern ==
41
42
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.
43
44
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".
45
46
Ecco un esempio di codice:
47
{{{
48 2 Amministratore Truelite
# Flyweight pattern
49
# La classe "TipoOggetto" mantiene informazione delle caratteristiche intrinseche degli oggetti (in comune)
50 1 Amministratore Truelite
class TipoOggetto(object):
51
        _listaOggetti = {}
52
        
53
        def __new__(cls, name):
54
                oggetto = TipoOggetto._listaOggetti.get(name,None)
55
                
56
                if not oggetto:
57
                        oggetto = object.__new__(cls)
58
                        TipoOggetto._listaOggetti[name] = oggetto
59
                return oggetto
60
61
62
        def __init__(self, name):
63
                self.name = name
64
                print id(self), name
65 2 Amministratore Truelite
66
# Per mostrare come un oggetto può avere delle caratteristiche estrinseche si deve creare
67
# un'altra classe che utilizzi due oggetti di cui uno di tipo "TipoOggetto"
68
69
class ProvaFlyweight:
70 1 Amministratore Truelite
        
71 2 Amministratore Truelite
        def __init__(self, name, altro):
72
                self.name = TipoOggetto(name)
73
                self.altro = altro
74 1 Amministratore Truelite
75 2 Amministratore Truelite
76
a = ProvaFlyweight("obj1", "1")
77
b = ProvaFlyweight("obj2", "2")
78
c = ProvaFlyweight("obj3", "3")
79
d = ProvaFlyweight("obj1", "4")
80
81
print id(a.name)
82
print id(b.name)
83
print id(c.name)
84
print id(d.name)
85
86
87
print id(a.altro)
88
print id(b.altro)
89
print id(c.altro)
90
print id(d.altro)
91
92 1 Amministratore Truelite
}}}
93 3 Amministratore Truelite
-1210465204 obj1
94 1 Amministratore Truelite
95 3 Amministratore Truelite
-1210465140 obj2
96 1 Amministratore Truelite
97 3 Amministratore Truelite
-1210465076 obj3
98
99
-1210465204 obj1
100
101
-1210465204
102
103
-1210465140
104
105
-1210465076
106
107
-1210465204
108
109
-1210102464
110
111
-1210465600
112
113
-1210465536
114
115
-1210465440
116 1 Amministratore Truelite
117 4 Amministratore Truelite
Come si può vedere dal risultato dell'esecuzione l'attributo "name" dell'instanza "a" e "d" sono un unico oggetto.
118 6 Amministratore Truelite
119
== Observer Pattern ==
120
121
Il pattern Observer definisce una dipendenza "uno a molti" tra oggetti. In questo pattern gli oggetti rivestono due ruoli: 
122
123
 * Subject (il soggetto)
124
 * Listeners (gli oggetti che ascoltano il soggetto)
125
126
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.
127
128
Ecco un esempio:
129
{{{
130
class Subject:
131
        __listeners = []
132
133
        def register(self, listener):
134
                self.__listeners.append(listener)
135
136
        def __notifyAll(self):
137
                for entry in self.__listeners:
138
                        entry.notify()
139
140
        def statusChanged(self):
141
                self.__notifyAll()
142
143
class Listener:
144
        
145
        def __init__(self, listenerName):
146
                self.name = listenerName
147
148
        def notify(self):
149
                print "Notify on listener ", self.name
150
151
s = Subject()
152
153
l1 = Listener("1")
154
l2 = Listener("2")
155
l3 = Listener("3")
156
l4 = Listener("4")
157
l5 = Listener("5")
158
159
160
s.register(l1)
161
s.register(l2)
162
s.register(l3)
163
s.register(l4)
164
s.register(l5)
165
166
s.statusChanged()
167
168
}}}
169 7 Amministratore Truelite
170
== Decorator Pattern ==
171 8 Amministratore Truelite
172
E' un pattern abbastanza semplice che è parte fondamentale dell'OOP. Serve per aggiungere funzionalità agli oggetti.
173
174
Vediamo un esempio:
175
{{{
176
class A:
177
        def __init__(self, b):
178
            """ b è una istanza della classe B"""
179
            self.b = b
180
181
        def __getattr__(self, name):
182
            """ I metodi/attributi di A non devono conoscere come sono delegati a b """
183
            return getattr(self.b, name)
184
185
186
b = B()
187
a = A(b)
188
}}}
189
190
Il metodo __getaddr__ viene chiamato quando non vengono trovati gli attributi, quindi in automatico si vanno a ricercare nella 
191
classe B, senza dovere distinguere le cose.