По моему опыту, некоторые паттерны все еще полезны в Python, и их даже проще настроить, чем в более статичных языках. Некоторые паттерны OTOH просто не нужны или даже не одобряются, как паттерн Singleton. Вместо этого используйте переменную уровня модуля или функцию. Или используйте шаблон Борга.
Вместо того, чтобы устанавливать шаблон создания, часто достаточно передать вызываемый объект, который создает объекты. Это может быть функция, объект с __call__
методом или даже класс, так как new()
в Python его нет, просто вызов самого класса:
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)
State и Strategy Pattern имеют очень похожую структуру в таких языках, как C ++ и Java. Меньше так в Python. Паттерн стратегии остается более или менее таким же, но паттерн состояний становится в основном ненужным. Шаблон состояния в статических языках имитирует изменение класса во время выполнения. В Python вы можете сделать это: изменить класс объекта во время выполнения. Пока вы делаете это контролируемым, инкапсулированным способом, у вас все будет хорошо:
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
Шаблоны, основанные на статической диспетчеризации типов, не будут работать или работать по-другому. Вам не нужно писать так много кода, например Visitor Pattern: в Java и C ++ вы должны писать метод accept в каждом доступном классе, тогда как в Python вы можете наследовать эту функциональность через класс mixin, например Visitable:
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)
Многие ситуации, в которых требуется применение Pattern на статическом языке, в Python делают не так много. Многие вещи могут быть решены с помощью других методов, таких как функции более высокого порядка (декораторы, фабрики функций) или мета-классы.