这些创造模式都是关于实例化一个或者若干个相关的对象的,让我们来看看他们是怎么用到上述两个原则的。 下面的小节有如下结构:面临的问题、解决方案、跟原则的关系。由于我们是用Python举例的,Python的 很多语言特性,比如鸭子类型、函数一等公民等等,可能会让这些模式看起来与传统的设计模式不太一样, 但是,道理是一样的。当然,如果考虑一些更加强大类型系统,比如代数数据类型,很多问题甚至都不存在, 比如抽象工厂想要解决的问题,实际上就是 Sum Type 和 Product Type 的组合。。
defprice(self) -> float: sum_price = 0 for item in self.contents: sum_price += item.price() return sum_price
defmain(): a = Product(1.0) b = Product(1.0) c = Box(contents=[ Product(1.0), Box( contents=[ Product(1.0) ] ), Box( contents=[ a, b ] ) ]) print(f"Price of c is {c.price()}")
from __future__ import annotations from abc import ABC, abstractmethod from typing importList
classVisitor(ABC): """ The Visitor Interface declares a set of visiting methods that correspond to component classes. The signature of a visiting method allows the visitor to identify the exact class of the component that it's dealing with. """
classConcreteComponentA(Component): """ Each Concrete Component must implement the `accept` method in such a way that it calls the visitor's method corresponding to the component's class. """
defexclusive_method_of_concrete_component_a(self) -> str: """ Concrete Components may have special methods that don't exist in their base class or interface. The Visitor is still able to use these methods since it's aware of the component's concrete class. """
return"A"
classConcreteComponentB(Component): """ Same here: visitConcreteComponentB => ConcreteComponentB """
defclient_code(components: List[Component], visitor: Visitor) -> None: """ The client code can run visitor operations over any set of elements without figuring out their concrete classes. The accept operation directs a call to the appropriate operation in the visitor object. """
# ... for component in components: component.accept(visitor) # ...
from __future__ import annotations from abc import ABC, abstractmethod from random import randrange from typing importList
classSubject(ABC): """ The Subject interface declares a set of methods for managing subscribers. """
@abstractmethod defattach(self, observer: Observer) -> None: """ Attach an observer to the subject. """ pass
@abstractmethod defdetach(self, observer: Observer) -> None: """ Detach an observer from the subject. """ pass
@abstractmethod defnotify(self) -> None: """ Notify all observers about an event. """ pass
classConcreteSubject(Subject): """ The Subject owns some important state and notifies observers when the state changes. """
_state: int = None """ For the sake of simplicity, the Subject's state, essential to all subscribers, is stored in this variable. """
_observers: List[Observer] = [] """ List of subscribers. In real life, the list of subscribers can be stored more comprehensively (categorized by event type, etc.). """
defattach(self, observer: Observer) -> None: print("Subject: Attached an observer.") self._observers.append(observer)
defnotify(self) -> None: """ Trigger an update in each subscriber. """ print("Subject: Notifying observers...") for observer in self._observers: observer.update(self)
defsome_business_logic(self) -> None: print("\nSubject: I'm doing something important.") self._state = randrange(0, 10) print(f"Subject: My state has just changed to: {self._state}") self.notify()
classObserver(ABC): """ The Observer interface declares the update method, used by subjects. """
classComplexCommand(Command): def__init__(self, receiver: Receiver, a, b) -> None: self._a = a self._b = b self._receiver = receiver defexecute(self): print(f"ComplexCommand execute with {self._receiver}") self._receiver.do_a(self._a) self._receiver.do_b(self._b)
classReceiver: """ 包含了业务逻辑,即知道如何响应命令。 """
defdo_a(self, a: str): print(f"{self} do a with {a}") defdo_b(self, b: str): print(f"{self} do b with {b}")
# 我们的状态机有两个状态,A 和 B classConcreteStateA(State): defhandle1(self) -> None: print("ConcreteStateA handles request1.") print("ConcreteStateA wants to change the state of the context.") self.context.transition_to(ConcreteStateB())
defhandle2(self) -> None: print("ConcreteStateB handles request2.") print("ConcreteStateB wants to change the state of the context.") self.context.transition_to(ConcreteStateA())
if __name__ == "__main__": context = Context(ConcreteStateA()) context.request1() context.request2()