En mi experiencia, algunos patrones siguen siendo útiles en Python, e incluso más fáciles de configurar que en lenguajes más estáticos. Algunos patrones OTOH simplemente no son necesarios, o incluso mal vistos, como el patrón Singleton. Utilice una variable o función de nivel de módulo en su lugar. O usa el patrón Borg.
En lugar de configurar un patrón de creación, a menudo es suficiente pasar un invocable que crea objetos. Esa podría ser una función, un objeto con un __call__
método o incluso una clase, ya que no hay new()
en Python, solo una invocación de la clase en sí:
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)
El patrón de estado y estrategia comparte una estructura muy similar en lenguajes como C ++ y Java. Menos en Python. El patrón de estrategia permanece más o menos igual, pero el patrón de estado se vuelve innecesario. El patrón de estado en lenguajes estáticos simula el cambio de clase en tiempo de ejecución. En Python, puede hacer exactamente eso: cambiar la clase de un objeto en tiempo de ejecución. Mientras lo haga de forma controlada y encapsulada, debería estar bien:
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
Los patrones que dependen del Despacho de tipo estático no funcionarán, o funcionarán de manera muy diferente. No tiene que escribir tanto código de placa de caldera, por ejemplo, Patrón de visitante: en Java y C ++ debe escribir un método de aceptación en cada clase visitable, mientras que en Python puede heredar esa funcionalidad a través de una clase mixin, como 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)
Muchas situaciones que requieren la aplicación de un Patrón en un lenguaje estático no lo hacen tanto en Python. Muchas cosas se pueden resolver con otras técnicas, como funciones de orden superior (decoradores, fábricas de funciones) o metaclases.