Nach meiner Erfahrung sind einige Muster in Python immer noch nützlich und noch einfacher einzurichten als in statischeren Sprachen. Einige Patterns OTOH werden einfach nicht benötigt oder sind sogar verpönt, wie das Singleton-Pattern. Verwenden Sie stattdessen eine Variable oder Funktion auf Modulebene. Oder verwenden Sie das Borg-Muster.
Anstatt ein Erstellungsmuster einzurichten, reicht es oft aus, ein aufrufbares Muster zu übergeben, das Objekte erstellt. Das kann eine Funktion, ein Objekt mit einer __call__
Methode oder sogar eine Klasse sein, da es new()
in Python keine gibt , nur einen Aufruf der Klasse selbst:
def make_da_thing(maker, other, stuff):
da_thing = maker(other + 1, stuff + 2)
# ... do sth
return da_thing
def maker_func(x, y):
return x * y
class MakerClass(object):
def __init__(self, x, y):
self.x = x
self.y = y
...
a = make_da_thing(maker_func, 5, 8)
b = make_da_thing(MakerClass, 6, 7)
Status- und Strategiemuster haben in Sprachen wie C ++ und Java eine sehr ähnliche Struktur. Weniger in Python. Das Strategiemuster bleibt mehr oder weniger gleich, aber das Zustandsmuster wird größtenteils unnötig. Das Zustandsmuster in statischen Sprachen simuliert den Klassenwechsel zur Laufzeit. In Python können Sie genau das tun: Ändern Sie die Klasse eines Objekts zur Laufzeit. Solange Sie dies kontrolliert und gekapselt tun, sollte es Ihnen gut gehen:
class On(object):
is_on = True
def switch(self):
self.__class__ = Off
class Off(object):
is_on = False
def switch(self):
self.__class__ = On
...
my_switch = On()
assert my_switch.is_on
my_switch.switch()
assert not my_switch.is_on
Muster, die auf statischem Typversand basieren, funktionieren nicht oder ganz anders. Sie müssen nicht so viel Code für die Kesselplatte schreiben, z. B. Besuchermuster: In Java und C ++ müssen Sie in jeder besuchbaren Klasse eine Akzeptanzmethode schreiben, während Sie in Python diese Funktionalität über eine Mixin-Klasse wie Visitable erben können:
class Visitable(object):
def accept(self, visitor):
visit = getattr(visitor, 'visit' + self.__class__.__name__)
return visit(self)
...
class On(Visitable):
''' exactly like above '''
class Off(Visitable):
''' exactly like above '''
class SwitchStatePrinter(object): # Visitor
def visitOn(self, switch):
print 'the switch is on'
def visitOff(self, switch):
print 'the switch is off'
class SwitchAllOff(object): # Visitor
def visitOn(self, switch):
switch.switch()
def visitOff(self, switch):
pass
...
print_state = SwitchStatePrinter()
turn_em_off = SwitchAllOff()
for each in my_switches:
each.accept(print_state)
each.accept(turn_em_off)
Viele Situationen, in denen ein Muster in einer statischen Sprache angewendet werden muss, tun dies in Python weniger. Viele Dinge können mit anderen Techniken gelöst werden, wie Funktionen höherer Ordnung (Dekoratoren, Funktionsfabriken) oder Metaklassen.