The Summary for 23 Kinds of Software Design in Pattern
- 這其實是拜託 Claud AI 請祂幫忙整理的 Summary 及代表範例,作為這個 Udemy Design Pattern in Python 課程系列筆記的總結。題外話,這次嘗試讓 AI 幫忙整理產生這麼長的摘要過程其實還蠻有趣的,每個範例還得實際跑一跑,以避免 AI 的幻覺問題影響到正確性~
1. 抽象工廠:
* 特點: 提供 Shape 家族的工廠介面來生成相關的對象
import abc
class AbstractFactory(abc.ABC):
@abc.abstractmethod
def create_product_a(self):
pass
@abc.abstractmethod
def create_product_b(self):
pass
class ConcreteFactory1(AbstractFactory):
def create_product_a(self):
return ConcreteProductA1()
def create_product_b(self):
return ConcreteProductB1()
class ConcreteFactory2(AbstractFactory):
def create_product_a(self):
return ConcreteProductA2()
def create_product_b(self):
return ConcreteProductB2()
class AbstractProductA(abc.ABC):
"""系列A產品介面"""
class ConcreteProductA1(AbstractProductA):
"""系列A的第1種產品實現"""
class ConcreteProductA2(AbstractProductA):
"""系列A的第2種產品實現"""
class AbstractProductB(abc.ABC):
"""系列B產品介面"""
class ConcreteProductB1(AbstractProductB):
"""系列B的第1種產品實現"""
class ConcreteProductB2(AbstractProductB):
"""系列B的第2種產品實現"""
2. 建造者(Builder) :
* 封裝複雜對象的建構過程,將内部表象與產品分離。
class Builder:
def build_part_a(self):
pass
def build_part_b(self):
pass
def build_part_c(self):
pass
class ConcreteBuilder(Builder):
def __init__(self):
self.product = Product()
def build_part_a(self):
self.product.add("PartA")
def build_part_b(self):
self.product.add("PartB")
def build_part_c(self):
self.product.add("PartC")
def get_result(self):
return self.product
class Product:
def __init__(self):
self.parts = []
def add(self, part):
self.parts.append(part)
builder = ConcreteBuilder()
builder.build_part_a()
builder.build_part_b()
builder.get_result() # 傳回 Product
3. 工廠方法(Factory Method):
* 將實例化操作推遲到子類別中進行~
import abc
class Creator(abc.ABC):
@abc.abstractmethod
def factory_method(self):
pass
def operate(self):
product = self.factory_method()
result = f"Creator operates with {product}"
return result
class ConcreteCreator(Creator):
def factory_method(self):
return ConcreteProduct()
class Product(abc.ABC):
pass
class ConcreteProduct(Product):
pass
creator = ConcreteCreator()
creator.operate()
4. 原型(Prototype):
* 用原型實例指定要建立物件的種類,並複製這些物件~
import copy
class Prototype:
def __init__(self):
self._objects = {}
def register(self, name, obj):
self._objects[name] = obj
def unregister(self, name):
del self._objects[name]
def clone(self, name, **attr):
obj = copy.deepcopy(self._objects.get(name))
obj.__dict__.update(attr)
return obj
class ConcretePrototype1:
def __init__(self):
self.x = 10
self.y = 20
prototype = Prototype()
prototype.register('q1', ConcretePrototype1())
prototype.clone('q1', x=100, y=200)
5. 單例(Singleton):
* 保證一個類別僅有一個實例,並提供該實例的全局訪問點。
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class Logger(metaclass=Singleton):
pass
logger1 = Logger()
logger2 = Logger()
logger1 is logger2 # True
6. 適配器(Adapter):
* 將一個類別的介面轉換成客戶期望的另一個介面。
class Target:
"""目標介面"""
def request(self):
return "Target: 特定請求"
class Adaptee:
"""被適配的類"""
def specific_request(self):
return ".eetpadA :求請特定"
class Adapter(Target):
"""適配器"""
def __init__(self, adaptee):
self.adaptee = adaptee
def request(self):
return f"Adapter: {self.adaptee.specific_request()[::-1]}"
target = Target()
adaptee = Adaptee()
adapter = Adapter(adaptee)
target.request()
adapter.request()
7. 橋接(Bridge):
* 將抽象部分與它的具體實現分離,使得二者可以獨立變化 。
class Abstraction:
def __init__(self, implementation):
self.implementation = implementation
def operation(self):
return (f"Abstraction: Base operation with:\n"
f"{self.implementation.operation_implementation()}")
class ExtendedAbstraction(Abstraction):
def operation(self):
return (f"ExtendedAbstraction: Extended operation with:\n"
f"{self.implementation.operation_implementation()}")
class Implementation:
def operation_implementation(self):
pass
class ConcreteImplementationA(Implementation):
def operation_implementation(self):
return "ConcreteImplementationA: Here's the result on the platform A."
class ConcreteImplementationB(Implementation):
def operation_implementation(self):
return "ConcreteImplementationB: Here's the result on the platform B."
abstraction = ExtendedAbstraction(ConcreteImplementationA())
abstraction.operation()
8. 組合(Composite):
* 將對象組合成樹狀結構來表達"部分-整體"的層次結構。
class Component:
def operation(self):
pass
class Leaf(Component):
def operation(self):
return "Leaf"
class Composite(Component):
def __init__(self):
self.children = []
def add(self, component):
self.children.append(component)
def remove(self, component):
self.children.remove(component)
def operation(self):
results = []
for child in self.children:
results.append(child.operation())
return f"Branch({'+'.join(results)})"
# 用法
simple = Leaf()
tree = Composite()
tree.add(Leaf())
tree.add(Leaf())
tree.operation()
9. 裝飾(Decorator):
* 為對象動態加入行為,而不影響其他對象。
class Component:
def operation(self):
pass
class ConcreteComponent(Component):
def operation(self):
return "ConcreteComponent"
class Decorator(Component):
def __init__(self, component):
self._component = component
@property
def component(self):
return self._component
def operation(self):
return self._component.operation()
class ConcreteDecoratorA(Decorator):
def operation(self):
return f"ConcreteDecoratorA({self.component.operation()})"
class ConcreteDecoratorB(Decorator):
def operation(self):
return f"ConcreteDecoratorB({self.component.operation()})"
# 用法
simple = ConcreteComponent()
decorator1 = ConcreteDecoratorA(simple)
decorator2 = ConcreteDecoratorB(decorator1)
decorator2.operation()
10. 外觀(Facade):
* 提供一個統一的介面,用來訪問子系統中的一群介面。
class Subsystem1:
"""子系統類"""
def operation1(self):
return "Subsystem1: Ready!"
# ...
class Subsystem2:
"""子系統類"""
def operation1(self):
return "Subsystem2: Get ready!"
# ...
class Subsystem3:
"""子系統類"""
def operation1(self):
return "Subsystem3: Fire!"
# ...
class Facade:
"""外觀類"""
def __init__(self):
self.sub1 = Subsystem1()
self.sub2 = Subsystem2()
self.sub3 = Subsystem3()
def operation(self):
results = []
results.append(self.sub1.operation1())
results.append(self.sub2.operation1())
results.append(self.sub3.operation1())
return "\n".join(results)
# 用法
facade = Facade()
facade.operation()
11. 享元(Flyweight):
* 重用共享的對象,以支持大量細粒度的對象。
import json
import random
class Flyweight:
def __init__(self, shared_state):
self.shared_state = shared_state
def operation(self, unique_state):
s = json.dumps(self.shared_state)
u = json.dumps(unique_state)
print(f"Flyweight: Displaying shared {s} and unique {u} state.", end="")
class FlyweightFactory:
_flyweights = {}
def __init__(self, initial_flyweights):
for state in initial_flyweights:
self._flyweights[self.get_key(state)] = Flyweight(state)
def get_key(self, state):
return "_".join(sorted(state))
def get_flyweight(self, shared_state):
key = self.get_key(shared_state)
if not self._flyweights.get(key):
print("FlyweightFactory: Can't find a flyweight, creating new one.")
self._flyweights[key] = Flyweight(shared_state)
else:
print("FlyweightFactory: Reusing existing flyweight.")
return self._flyweights[key]
def list_flyweights(self):
count = len(self._flyweights)
print(f"FlyweightFactory: I have {count} flyweights:")
print("\n".join(map(str, self._flyweights.keys())), end="")
# 用法
factory = FlyweightFactory([
["Chevrolet", "Camaro2018", "pink"],
["Mercedes Benz", "C300", "black"],
["Mercedes Benz", "C500", "red"]
])
factory.list_flyweights()
fl1 = factory.get_flyweight(["pink"])
fl2 = factory.get_flyweight(["red","4-doors"])
fl3 = factory.get_flyweight(["black"])
fl1.operation(["10"])
fl2.operation(["V8"])
fl3.operation([])
12. 代理(Proxy):
* 使用代理對象來代替其他對象控制訪問。
from abc import ABC, abstractmethod
class Subject(ABC):
"""定義RealSubject與Proxy的通用接口"""
@abstractmethod
def request(self):
pass
class RealSubject(Subject):
"""定義Proxy所代表的實體類"""
def request(self):
print("RealSubject: Handling request.")
class Proxy(Subject):
"""保存一個引用使得Proxy可以訪問實體對象"""
def __init__(self, real_subject):
self._real_subject = real_subject
def request(self):
"""通過保護代理添加一個控制層"""
print("Proxy: Checking access prior to firing a real request.")
self._real_subject.request()
# 用法
real = RealSubject()
proxy = Proxy(real)
proxy.request()
13. 鏈式責任(Chain of Responsibility):
* 使多個對象都有可能處理請求,從而避免請求的發送者和接收者之間的耦合關系。
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any
class Handler(ABC):
"""定義一個處理請求的介面"""
@abstractmethod
def set_next(self, handler: Handler) -> Handler:
pass
@abstractmethod
def handle(self, request) -> None:
pass
class BaseHandler(Handler):
""" 鏈中最後一個處理者,通常做默認處理 """
def set_next(self, handler: Handler) -> Handler:
pass
def handle(self, request):
print("End of chain, no handler for this request!")
class AbstractHandler(Handler):
"""鏈中的處理者,通過一個字段組合該鏈"""
_next_handler: Handler = None
def set_next(self, handler: Handler) -> Handler:
self._next_handler = handler
return handler
@abstractmethod
def handle(self, request: Any) -> None:
if self._next_handler:
return self._next_handler.handle(request)
return None
class ConcreteHandler1(AbstractHandler):
"""定義具體處理者"""
def handle(self, request: Any) -> str:
if request == "one":
print("ConcreteHandler1 handled request")
return
super().handle(request)
class ConcreteHandler2(AbstractHandler):
"""定義具體處理者"""
def handle(self, request: Any) -> str:
if request == "two":
print("ConcreteHandler2 handled request")
return
super().handle(request)
# 用法
def client_code(handler: Handler) -> None:
for request in ["one", "two", "three"]:
print(f"\nClient: Who wants to handle {request}?")
handler.handle(request)
base = BaseHandler()
h1 = ConcreteHandler1()
h2 = ConcreteHandler2()
h1.set_next(h2).set_next(base)
client_code(h1)
14. 命令(Command):
* 封裝請求為對象,從而可以使用不同的請求把客戶和接收者解耦。
from __future__ import annotations
from abc import ABC, abstractmethod
class Command(ABC):
"""定義命令接口"""
@abstractmethod
def execute(self) -> None:
pass
class SimpleCommand(Command):
"""定義一些命令"""
def __init__(self, payload: str) -> None:
self._payload = payload
def execute(self) -> None:
print(f"SimpleCommand: See, I can do simple things like printing ({self._payload})")
class ComplexCommand(Command):
"""示範可以封裝任何數量的命令"""
def __init__(self, receiver: Receiver, a: str, b: str) -> None:
"""複雜命令可以定義一系列命令"""
self._receiver = receiver
self._a = a
self._b = b
def execute(self) -> None:
"""命令的執行方法"""
print("ComplexCommand: Complex stuff should be done by a receiver object", end="")
self._receiver.do_something(self._a)
self._receiver.do_something_else(self._b)
class Receiver:
"""示範命令協作對象"""
def do_something(self, a: str) -> None:
print(f"\nReceiver: Working on ({a}.)", end="")
def do_something_else(self, b: str) -> None:
print(f"\nReceiver: Also working on ({b}.)", end="")
class Invoker:
"""要求提供命令接口的調用方"""
_on_start = None
_on_finish = None
def set_on_start(self, command: Command):
self._on_start = command
def set_on_finish(self, command: Command):
self._on_finish = command
def do_something_important(self) -> None:
print("Invoker: Does anybody want something done before I begin?")
if isinstance(self._on_start, Command):
self._on_start.execute()
print("Invoker: ...doing something really important...")
print("Invoker: Does anybody want something done after I finish?")
if isinstance(self._on_finish, Command):
self._on_finish.execute()
# 用法
invoker = Invoker()
invoker.set_on_start(SimpleCommand("Say Hi!"))
receiver = Receiver()
invoker.set_on_finish(ComplexCommand(
receiver, "Send email", "Save report"))
invoker.do_something_important()
15. 解譯器(Interpreter):
* 給每個語法規則提供一個對應的解譯類別。
from abc import ABC, abstractmethod
from typing import List
class Expression(ABC):
"""定義剖析器規則的基類"""
@abstractmethod
def interpret(self):
pass
class TerminalExpression(Expression):
"""終端符號剖析規則"""
def __init__(self, data) -> None:
self.data = data
def interpret(self):
return self.data
class NonterminalExpression(Expression):
"""非終端符號剖析規則"""
def __init__(self, expression: List[Expression]) -> None:
self.expression = expression
def interpret(self):
result = []
for exp in self.expression:
value = exp.interpret()
result.append(value)
return ' '.join(result)
# 用法
ast = [
TerminalExpression("Hello"),
TerminalExpression("World")
]
nonterminal = NonterminalExpression(ast)
nonterminal.interpret()
16. 迭代器(Iterator):
* 提供一種順序訪問一系列對象的方法,而不需要暴露這些對象的內部細節。
class AlphabeticalOrderIterator:
"""具體迭代器"""
_position: int = None
"""迭代器應該追蹤它們所迭代的當前項目"""
_reverse: bool = False
def __init__(self, collection, reverse: bool = False) -> None:
self._collection = collection
self._reverse = reverse
self._position = -1 if reverse else 0
def __next__(self):
"""移動到下一個元素"""
try:
value = self._collection[self._position]
self._position += -1 if self._reverse else 1
except IndexError:
raise StopIteration()
return value
def __iter__(self):
return self
# 用法
collection = ["a", "b", "c", "d"]
iterator = AlphabeticalOrderIterator(collection)
for item in iterator:
print(item)
# 反向迭代
reverse_iterator = AlphabeticalOrderIterator(collection, reverse=True)
for item in reverse_iterator:
print(item)
17. 中介者(Mediator):
* 用中介對象去封裝一系列摯交組的互動,降低他們的依賴性。
from __future__ import annotations
from abc import ABC
class Mediator(ABC):
"""定義一個接口用於組件與中介者的通信"""
def notify(self, sender: object, event: str) -> None:
pass
class ConcreteMediator(Mediator):
def __init__(self, component1, component2):
self.component1 = component1
self.component1.mediator = self
self.component2 = component2
self.component2.mediator = self
def notify(self, sender, event):
if event == "A":
print("中介者 reacts on A and triggers folowing operations:")
self.component2.do_c()
elif event == "D":
print("中介者 reacts on D and triggers following operations:")
self.component1.do_b()
self.component2.do_c()
class BaseComponent:
"""各組件共同點,知曉中介者"""
def __init__(self, mediator: Mediator = None) -> None:
self._mediator = mediator
@property
def mediator(self) -> Mediator:
return self._mediator
@mediator.setter
def mediator(self, mediator: Mediator) -> None:
self._mediator = mediator
class Component1(BaseComponent):
"""具體組件 1"""
def do_a(self):
print("Component 1 does A.")
self.mediator.notify(self, "A")
def do_b(self):
print("Component 1 does B.")
self.mediator.notify(self, "B")
class Component2(BaseComponent):
"""具體組件 2"""
def do_c(self):
print("Component 2 does C.")
self.mediator.notify(self, "C")
def do_d(self):
print("Component 2 does D.")
self.mediator.notify(self, "D")
# 用法
c1 = Component1()
c2 = Component2()
mediator = ConcreteMediator(c1, c2)
print("Client triggets operation A.")
c1.do_a()
print()
print("Client triggers operation D.")
c2.do_d()
18. 備忘模式(Memento):
* 在不破壞封裝性的前提下擷取一個對象的內部狀態以便以後恢復。
import datetime
class Memento:
def __init__(self, state):
self._state = state
self._date = datetime.date.today()
def get_state(self):
return self._state
def get_date(self):
return self._date
class Originator:
def __init__(self, state):
self._state = state
def create_memento(self):
print(f"Originator: Saving {self._state}")
return Memento(self._state)
def get_state(self):
return self._state
def set_memento(self, memento):
self._state = memento.get_state()
print(f"Originator: Previous state {self._state} restored")
originator = Originator("State 1")
memento = originator.create_memento()
originator._state = "State 2"
print(f"Originator: Current State = {originator._state}")
originator.set_memento(memento)
print(f"Originator: Current State = {originator._state}")
19. 觀察者(Observer):
* 定義對象和觀察者之間的依賴關系,使得當對象改變狀態時,其相關依賴都會得到通知並更新。
from __future__ import annotations
from abc import ABC, abstractmethod
from random import randrange
from typing import List
class Subject(ABC):
"""定義主題接口"""
@abstractmethod
def attach(self, observer: Observer) -> None:
"""附加觀察者"""
pass
@abstractmethod
def detach(self, observer: Observer) -> None:
"""分離觀察者"""
pass
@abstractmethod
def notify(self) -> None:
"""發送更新給連線的觀察者"""
pass
class ConcreteSubject(Subject):
"""定義主題"""
_state: int = None
"""一些重要狀態,觀察者留意"""
_observers: List[Observer] = []
"""所有當前註冊的觀察者列表"""
def attach(self, observer: Observer) -> None:
print("Subject: Attached an observer.")
self._observers.append(observer)
def detach(self, observer: Observer) -> None:
self._observers.remove(observer)
"""根據主體內部狀態發送更新給觀察者"""
def notify(self) -> None:
print("Subject: Notifying observers...")
for observer in self._observers:
observer.update(self)
def some_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()
class Observer(ABC):
"""定義觀察者接口"""
@abstractmethod
def update(self, subject: Subject) -> None:
"""接收更新時調用"""
pass
class ConcreteObserverA(Observer):
def update(self, subject: Subject) -> None:
if subject._state < 3:
print("ConcreteObserverA: Reacted to the event")
class ConcreteObserverB(Observer):
def update(self, subject: Subject) -> None:
if subject._state == 0 or subject._state >= 2:
print("ConcreteObserverB: Reacted to the event")
# 用法
subject = ConcreteSubject()
observer_a = ConcreteObserverA()
subject.attach(observer_a)
observer_b = ConcreteObserverB()
subject.attach(observer_b)
subject.some_business_logic()
subject.some_business_logic()
subject.detach(observer_a)
subject.some_business_logic()
20. 狀態(State):
* 允許對象在內部狀態改變時改變行為,對象看起來好像改變了類別一樣。
from abc import ABC, abstractmethod
class Context:
"""定義通過轉換狀態 Context 類的接口。保存一個具體狀態的實例"""
_state = None
"""狀態實例"""
def __init__(self, state) -> None:
self.transition_to(state)
def transition_to(self, state):
"""切換狀態"""
print(f"Context: Transition to {type(state).__name__}")
self._state = state
self._state.context = self
"""調用者會將請求委派給當前狀態"""
def request1(self):
self._state.handle1()
def request2(self):
self._state.handle2()
class State(ABC):
"""定義一個接口用於封裝與 Context 的一種特定狀態相關的行為"""
@property
def context(self) -> Context:
return self._context
@context.setter
def context(self, context: Context) -> None:
self._context = context
@abstractmethod
def handle1(self):
pass
@abstractmethod
def handle2(self):
pass
"""具體狀態"""
class ConcreteStateA(State):
def handle1(self):
print("ConcreteStateA handles request1.")
def handle2(self):
print("ConcreteStateA handles request2.")
self.context.transition_to(ConcreteStateB())
class ConcreteStateB(State):
def handle1(self):
print("ConcreteStateB handles request1.")
def handle2(self):
print("ConcreteStateB handles request2.")
self.context.transition_to(ConcreteStateA())
# 用法
context = Context(ConcreteStateA())
context.request1()
context.request2()
21. 策略(Strategy):
* 定義一系列演算法,分別封裝起來,使得它們可以互換。
from abc import ABC, abstractmethod
class Strategy(ABC):
"""定義策略類的接口"""
@abstractmethod
def execute(self, data):
pass
"""實現各類策略"""
class ConcreteStrategyA(Strategy):
def execute(self, data):
print("Strategy A: ", data)
class ConcreteStrategyB(Strategy):
def execute(self, data):
print("Strategy B: ", data)
class Context():
"""使控制該策略的父級"""
def __init__(self, strategy: Strategy) -> None:
"""屬於 Context 的某策略"""
self._strategy = strategy
@property
def strategy(self) -> Strategy:
"""策略切換"""
return self._strategy
@strategy.setter
def strategy(self, strategy: Strategy) -> None:
"""改變策略通過 Context 聲明"""
self._strategy = strategy
def do_some_business_logic(self):
"""Context 提供資訊給 strategy 執行演算法"""
print("Context: Sorting data using the strategy (not sure how it'll do it)")
result = self._strategy.execute(["a", "b", "c", "d", "e"])
print(result)
# 用法
context = Context(ConcreteStrategyA())
print("Client: Strategy is set to normal sorting.")
context.do_some_business_logic()
print()
context.strategy = ConcreteStrategyB()
print("Client: Strategy is set to reverse sorting.")
context.do_some_business_logic()
22. 範本模式(Template Pattern):
* 將算法的一些步驟推遲到子類別中實現,子類別無需改變算法的結構即可重定義該算法的某些步驟。
from abc import ABC, abstractmethod
class AbstractClass(ABC):
"""定義模板方法的框架"""
def template_method(self) -> None:
"""模板方法定義了一個演算法的框架"""
self.base_operation1()
self.required_operations1()
self.base_operation2()
self.hook1()
self.required_operations2()
self.base_operation3()
self.hook2()
"""對子類別來說是選擇性的模板方法"""
def base_operation1(self) -> None:
print("AbstractClass says: I am doing the bulk of the work")
def base_operation2(self) -> None:
print("AbstractClass says: But I let subclasses override some operations")
def base_operation3(self) -> None:
print("AbstractClass says: But I am doing the bulk of the work anyway")
"""隨主類別實現"""
@abstractmethod
def required_operations1(self) -> None:
pass
@abstractmethod
def required_operations2(self) -> None:
pass
"""這些行為有默認實現"""
def hook1(self) -> None:
pass
def hook2(self) -> None:
pass
class ConcreteClass1(AbstractClass):
"""定義具體子類"""
def required_operations1(self) -> None:
print("ConcreteClass1 says: Implemented Operation1")
def required_operations2(self) -> None:
print("ConcreteClass1 says: Implemented Operation2")
class ConcreteClass2(AbstractClass):
"""定義另一個子類"""
def required_operations1(self) -> None:
print("ConcreteClass2 says: Implemented Operation1")
def required_operations2(self) -> None:
print("ConcreteClass2 says: Implemented Operation2")
def client_code(abstract_class: AbstractClass) -> None:
"""模板方法在客戶端代碼工作"""
abstract_class.template_method()
# 用法
print("Same client code can work with different subclasses:")
client_code(ConcreteClass1())
client_code(ConcreteClass2())
23. 訪問者(Visitor):
* 表示作用在某物件結構上的操作,它使你可以在不改變這些類別的前提下定義作用在這些元素的新操作。
from __future__ import annotations
from abc import ABC, abstractmethod
class Component(ABC):
"""定義一個訪問者可以在的所有元素的接口"""
@abstractmethod
def accept(self, visitor: Visitor) -> None:
pass
class ConcreteComponentA(Component):
"""各部分會實現導入訪問者的 accept() 方法"""
def accept(self, visitor: Visitor) -> None:
"""訪問者在必要時可能獲取被訪問元素"""
visitor.visit_concrete_component_a(self)
def exclusive_method_of_concrete_component_a(self) -> str:
"""具體元素也可以定義自己的業務邏輯"""
return "A"
class ConcreteComponentB(Component):
"""同理,其他元素實現 accept 方法"""
def accept(self, visitor: Visitor):
visitor.visit_concrete_component_b(self)
def special_method_of_concrete_component_b(self) -> str:
return "B"
class Visitor(ABC):
"""定義訪問者將必須實現的接口"""
@abstractmethod
def visit_concrete_component_a(self, element: ConcreteComponentA) -> None:
pass
@abstractmethod
def visit_concrete_component_b(self, element: ConcreteComponentB) -> None:
pass
"""具體訪問者將在每個新具體元素類時實現一些業務邏輯"""
class ConcreteVisitor1(Visitor):
def visit_concrete_component_a(self, element) -> None:
print(f"{element.exclusive_method_of_concrete_component_a()} + ConcreteVisitor1")
def visit_concrete_component_b(self, element) -> None:
print(f"{element.special_method_of_concrete_component_b()} + ConcreteVisitor1")
class ConcreteVisitor2(Visitor):
def visit_concrete_component_a(self, element) -> None:
print(f"{element.exclusive_method_of_concrete_component_a()} + ConcreteVisitor2")
def visit_concrete_component_b(self, element) -> None:
print(f"{element.special_method_of_concrete_component_b()} + ConcreteVisitor2")
def client_code(components: list, visitor: Visitor) -> None:
"""客戶端代碼透過 accept 方法對各組件運行訪問者"""
for component in components:
component.accept(visitor)
# 用法
components = [ConcreteComponentA(), ConcreteComponentB()]
print("The client code works with all visitors via the base Visitor interface:")
visitor1 = ConcreteVisitor1()
client_code(components, visitor1)
print()
visitor2 = ConcreteVisitor2()
client_code(components, visitor2)