TypeScript
创建型模式
创建型模式关注对象的创建机制,帮助使系统独立于对象的创建、组合和表示方式。
1. **单例模式(Singleton)**:确保一个类只有一个实例,并提供一个全局访问点。
2. **工厂方法模式(Factory Method)**:定义一个用于创建对象的接口,让子类决定实例化哪一个类。
3. **抽象工厂模式(Abstract Factory)**:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
4. **建造者模式(Builder)**:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
5. **原型模式(Prototype)**:通过复制现有的实例来创建新的实例,而不是通过新建类。
结构型模式
结构型模式关注类和对象的组合,继承的概念被用来组合接口和定义组合对象获得新功能的方式。
1. **适配器模式(Adapter)**:允许将一个类的接口转换成客户期望的另一个接口,使原本接口不兼容的类可以一起工作。
2. **桥接模式(Bridge)**:将抽象部分与实现部分分离,使它们可以独立变化。
3. **组合模式(Composite)**:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
4. **装饰器模式(Decorator)**:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。
5. **外观模式(Facade)**:提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,使得子系统更容易使用。
6. **享元模式(Flyweight)**:运用共享技术有效地支持大量细粒度的对象。
7. **代理模式(Proxy)**:为其他对象提供一种代理以控制对这个对象的访问。
行为型模式
行为型模式关注对象之间的职责分配。它们处理对象之间的通信,增强对象之间的协作。
1. **责任链模式(Chain of Responsibility)**:为请求创建一个接收者对象的链。
2. **命令模式(Command)**:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。
3. **解释器模式(Interpreter)**:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
4. **迭代器模式(Iterator)**:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露其内部的表示。
5. **中介者模式(Mediator)**:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
6. **备忘录模式(Memento)**:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
7. **观察者模式(Observer)**:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
8. **状态模式(State)**:允许一个对象在其内部状态改变时改变它的行为。
9. **策略模式(Strategy)**:定义一系列的算法,把它们一个个封装起来,并使它们可相互替换。
10. **模板方法模式(Template Method)**:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
11. **访问者模式(Visitor)**:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
单例模式
单例模式确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。
class Singleton:
_instance = None
@staticmethod
def getInstance():
if Singleton._instance == None:
Singleton._instance = Singleton()
return Singleton._instance
# 使用
s = Singleton.getInstance()
适用场景:当你想确保全局使用一个共享资源(如配置文件、数据库连接等)时。
优点:可以确保一个类只有一个实例,减少了内存开销,尤其是当一个对象的创建和销毁比较频繁时。
缺点:违反了单一职责原则,因为它同时解决了两个问题(控制实例的创建和保存实例)。在多线程环境下需要特别小心,如果不正确实现可能会导致多个实例。
工厂方法模式
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类。
class Button:
def render(self):
pass
class WindowsButton(Button):
def render(self):
print("Windows button")
class LinuxButton(Button):
def render(self):
print("Linux button")
class ButtonFactory:
def create_button(self, os_type):
if os_type == "Windows":
return WindowsButton()
elif os_type == "Linux":
return LinuxButton()
else:
raise ValueError("OS type not supported")
# 使用
factory = ButtonFactory()
button = factory.create_button("Windows")
button.render()
适用场景:当一个类不知道它所必须创建的对象的类的时候;当一个类希望由它的子类来指定它所创建的对象时。
优点:提高了系统的可扩展性,因为增加新的具体产品类不需要修改已有的代码,满足开闭原则。
缺点:可能会导致系统中类的个数增加,增加了系统的复杂度。
抽象工厂模式
抽象工厂模式提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
class Button:
def paint(self):
pass
class LinuxButton(Button):
def paint(self):
print("Render a button in a Linux style")
class WindowsButton(Button):
def paint(self):
print("Render a button in a Windows style")
class GUIFactory:
def create_button(self):
pass
class LinuxFactory(GUIFactory):
def create_button(self):
return LinuxButton()
class WindowsFactory(GUIFactory):
def create_button(self):
return WindowsButton()
# 使用
factory = LinuxFactory()
button = factory.create_button()
button.paint()
适用场景:当需要创建一组相关或相互依赖的对象时;当你想提供一个库或框架,让用户能够扩展或定制其内部的组件时。
优点:可以确保同一工厂生产的产品相互匹配;支持易于交换产品系列;增强了程序的抽象性和可维护性。
缺点:难以支持新种类的产品。这是因为抽象工厂接口确定了可以被创建的产品集合,支持新种类的产品就需要扩展该工厂接口,这将涉及抽象工厂类及其所有子类的改变。
建造者模式
建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
class Car:
def __init__(self):
self.parts = []
def add(self, part):
self.parts.append(part)
def describe(self):
print("Car parts: " + ", ".join(self.parts))
class CarBuilder:
def __init__(self):
self.car = Car()
def add_engine(self):
self.car.add("Engine")
return self
def add_wheels(self):
self.car.add("4 wheels")
return self
def build(self):
return self.car
# 使用
builder = CarBuilder()
car = builder.add_engine().add_wheels().build()
car.describe()
适用场景:当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时;当构造过程必须允许被构造的对象有不同的表示时。
优点:可以更精细地控制对象的构造过程;可以将复杂构造过程的代码从产品的业务逻辑中分离出来。
缺点:设计复杂,会增加系统的理解难度和运行成本。
适配器模式(Adapter)
适配器模式允许将一个类的接口转换成客户期望的另一个接口。适配器模式让原本接口不兼容的类可以合作无间。
class Target:
def request(self):
return "Target: The default target's behavior."
class Adaptee:
def specific_request(self):
return ".eetpadA eht fo roivaheb laicepS"
class Adapter(Target, Adaptee):
def request(self):
return f"Adapter: (TRANSLATED) {self.specific_request()[::-1]}"
# 使用
target = Adapter()
print(target.request())
适用场景:当你希望使用某个类,但是它的接口与其他代码不兼容时;当你想创建一个可重用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作时。
优点:单一职责原则,可以将接口或数据转换代码从程序主要业务逻辑中分离;增加了类的透明性和复用性;灵活性和扩展性增强。
缺点:增加了代码的复杂度;有时候很难支持适配器的所有功能,因为一些被适配的类可能并没有提供足够的功能。
观察者模式(Observer)
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self):
for observer in self._observers:
observer.update(self)
class ConcreteSubject(Subject):
_state = None
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify()
class Observer:
def update(self, subject):
pass
class ConcreteObserverA(Observer):
def update(self, subject):
if subject.state < 3:
print("ConcreteObserverA: Reacted to the event")
class ConcreteObserverB(Observer):
def update(self, subject):
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.state = 2
适用场景:当一个对象的改变需要同时改变其他对象,而且你不知道具体有多少对象需要被改变时;当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面分离在独立的对象中可以使它们可以独立地改变和复用。
优点:支持简单的广播通信,自动通知所有已订阅的对象;目标和观察者之间的抽象耦合最小;支持运行时添加和删除观察者。
缺点:如果观察者和订阅者之间有循环依赖,可能会导致系统崩溃;观察者列表一旦很长,通知的时间可能会很长。
装饰器模式(Decorator)
装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有类的一个包装。
class Component:
def operation(self):
pass
class ConcreteComponent(Component):
def operation(self):
return "ConcreteComponent"
class Decorator(Component):
_component = None
def __init__(self, component):
self._component = component
@property
def component(self):
return self._component
def operation(self):
if self._component:
return self._component.operation()
else:
return ""
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)
print(decorator2.operation())
适用场景:当你希望给对象动态地添加职责,而不影响其他对象时;当扩展一个类的功能比继承更灵活时。
优点:比继承更灵活;可以通过一种动态的方式来扩展一个对象的功能;可以用添加和删除的方式来增加或删除对象的行为。
缺点:会导致系统中出现很多小对象,增加了系统的复杂度;更难理解。
策略模式(Strategy)
策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。
class Strategy:
def do_operation(self, num1, num2):
pass
class OperationAdd(Strategy):
def do_operation(self, num1, num2):
return num1 + num2
class OperationSubtract(Strategy):
def do_operation(self, num1, num2):
return num1 - num2
class OperationMultiply(Strategy):
def do_operation(self, num1, num2):
return num1 * num2
class Context:
def __init__(self, strategy):
self._strategy = strategy
def execute_strategy(self, num1, num2):
return self._strategy.do_operation(num1, num2)
# 使用
context = Context(OperationAdd())
print("10 + 5 = " + str(context.execute_strategy(10, 5)))
context = Context(OperationSubtract())
print("10 - 5 = " + str(context.execute_strategy(10, 5)))
context = Context(OperationMultiply())
print("10 * 5 = " + str(context.execute_strategy(10, 5)))
适用场景:当你有很多类似的类,但它们在执行某些行为上有所不同时;当你想避免使用多重条件选择语句,如 if-else 或 switch-case。
优点:可以定义一系列可重用的算法或行为;可以将算法的实现细节从使用它的客户代码中隔离开来;可以用替换算法的方式动态地改变对象的行为。
缺点:客户必须了解不同的策略;增加了对象的数目。
状态模式(State)
状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来好像修改了它的类。
class State:
def do_action(self, context):
pass
class StartState(State):
def do_action(self, context):
print("Player is in start state")
context.state = self
class StopState(State):
def do_action(self, context):
print("Player is in stop state")
context.state = self
class Context:
state = None
def __init__(self):
self.state = None
def get_state(self):
return self.state
def set_state(self, state):
self.state = state
def do_action(self):
self.state.do_action(self)
# 使用
context = Context()
start_state = StartState()
start_state.do_action(context)
print(context.get_state())
stop_state = StopState()
stop_state.do_action(context)
print(context.get_state())
适用场景:当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时;当代码中包含大量与对象状态有关的条件语句时。
优点:封装了转换规则;枚举可能的状态,在枚举状态之前将所有的状态转换逻辑集中;将所有与某个状态相关的行为放到一个类中。
缺点:如果状态很多,导致状态类膨胀。
命令模式(Command)
命令模式将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
class Command:
def execute(self):
pass
class Light:
def on(self):
print("Light is on")
def off(self):
print("Light is off")
class LightOnCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.on()
class LightOffCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.off()
class RemoteControl:
def submit(self, command):
command.execute()
# 使用
light = Light()
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)
remote = RemoteControl()
remote.submit(light_on)
remote.submit(light_off)
适用场景:当你需要将发出请求的操作和执行请求的操作解耦时;当你需要支持撤销操作时;当你需要支持操作的日志记录和可恢复功能时。
优点:降低了系统耦合度;新的命令可以很容易地加入到系统中;可以比较容易地设计一个组合命令。
缺点:可能会导致某些系统有过多的具体命令类。
中介者模式(Mediator)
中介者模式定义了一个对象,该对象封装了一系列对象之间的交互方式,使得这些对象之间不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
class Mediator:
def notify(self, sender, event):
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("Mediator reacts on A and triggers following operations:")
self._component2.do_c()
elif event == "D":
print("Mediator reacts on D and triggers following operations:")
self._component1.do_b()
class BaseComponent:
def __init__(self, mediator=None):
self._mediator = mediator
@property
def mediator(self):
return self._mediator
@mediator.setter
def mediator(self, mediator):
self._mediator = mediator
class Component1(BaseComponent):
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):
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)
c1.do_a()
c2.do_d()
适用场景:当一组对象以定义良好但复杂的方式进行通信时;当想要避免多个对象间的紧密耦合时;当想定制一个分布在多个类中的行为,而又不想生成太多的子类时。
优点:减少了类之间的依赖关系,将一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖关系,降低了类间的耦合。
缺点:中介者会变得过于复杂,系统中会增加一个中介者类,因为所有的关系都集中在中介者中,所以中介者的复杂性可能会很大。
享元模式(Flyweight)
享元模式使用共享对象可有效地支持大量的细粒度的对象,以减少应用程序的内存占用。
class Flyweight:
def __init__(self, shared_state):
self._shared_state = shared_state
def operation(self, unique_state):
s = str(self._shared_state)
u = str(unique_state)
print(f"Flyweight: Displaying shared ({s}) and unique ({u}) state.")
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())))
# 使用
factory = FlyweightFactory([["Chevrolet", "Camaro2018", "pink"], ["Mercedes Benz", "C300", "black"], ["Mercedes Benz", "C500", "red"], ["BMW", "M5", "red"], ["BMW", "X6", "white"]])
factory.list_flyweights()
add_car_to_police_database(factory, "CL234IR", "Chevrolet", "Camaro2018", "pink")
factory.list_flyweights()
def add_car_to_police_database(factory, plates, brand, model, color):
print("\nClient: Adding a car to database.")
flyweight = factory.get_flyweight([brand, model, color])
flyweight.operation([plates])
适用场景:当一个程序需要生成大量的相似对象时;当由于大量的对象造成很大的存储开销时。
优点:大大减少了系统中的对象数量;节省了系统资源,提高了性能。
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,使得编程复杂度增加。
组合模式(Composite)
组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
class Component:
def add(self, component):
pass
def remove(self, component):
pass
def is_composite(self):
return False
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 is_composite(self):
return True
def operation(self):
results = []
for child in self._children:
results.append(child.operation())
return f"Branch({'+'.join(results)})"
# 使用
tree = Composite()
branch1 = Composite()
branch1.add(Leaf())
branch1.add(Leaf())
branch2 = Composite()
branch2.add(Leaf())
tree.add(branch1)
tree.add(branch2)
print(tree.operation())
适用场景:当你想表示对象的部分-整体层次结构时;当你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象时。
优点:可以清楚地定义层次复杂的复合对象,使得代码更加清晰;客户端可以一致地使用复合结构和单个对象。
缺点:设计变得更加抽象,客户端需要花更多时间理解这些结构,尤其是在新添加类和树构建代码方面。
代理模式(Proxy)
代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。使用代理模式创建代表对象,让代表对象控制某对象的访问,并且可以在不改变客户端代码的情况下添加一些额外的处理(如访问控制、延迟初始化、监视、日志记录、缓存等)。
class Subject:
def request(self):
pass
class RealSubject(Subject):
def request(self):
print("RealSubject: Handling request.")
class Proxy(Subject):
def __init__(self, real_subject):
self._real_subject = real_subject
def request(self):
if self.check_access():
self._real_subject.request()
self.log_access()
def check_access(self):
print("Proxy: Checking access prior to firing a real request.")
return True
def log_access(self):
print("Proxy: Logging the time of request.")
# 使用
real_subject = RealSubject()
proxy = Proxy(real_subject)
proxy.request()
适用场景:当需要用较小的对象代表一个复杂对象时;当对象需要被远程访问时;当需要控制对原始对象的访问时,以便在访问对象时执行一些附加操作。
优点:可以在客户端毫无察觉的情况下控制对象;可以管理对象的生命周期;代理模式在客户端和目标对象之间起到一个中介的作用和保护目标对象的作用;代理对象可以扩展目标对象的功能。
缺点:可能会导致处理速度变慢;增加了系统的复杂度。
桥接模式(Bridge)
桥接模式将抽象部分与实现部分分离,使它们都可以独立地变化。通过组合的方式建立两个类之间的联系,而不是继承。
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."
class Abstraction:
def __init__(self, implementation):
self._implementation = implementation
def operation(self):
return ("Abstraction: Base operation with:\n" +
self._implementation.operation_implementation())
class ExtendedAbstraction(Abstraction):
def operation(self):
return ("ExtendedAbstraction: Extended operation with:\n" +
self._implementation.operation_implementation())
# 使用
implementation = ConcreteImplementationA()
abstraction = Abstraction(implementation)
print(abstraction.operation())
implementation = ConcreteImplementationB()
abstraction = ExtendedAbstraction(implementation)
print(abstraction.operation())
适用场景:当你想避免一个抽象和它的实现之间的永久绑定时;当抽象和实现都应该通过子类化来扩展时;当你想在几个对象间共享实现但同时要避免代码重复时。
优点:你可以创建与平台无关的类和程序;客户端代码仅与高层的抽象部分互动,不会接触到平台的细节;开闭原则。你可以新增抽象和实现部分而不互相影响。
缺点:增加了系统的复杂度。
责任链模式(Chain of Responsibility)
责任链模式为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。
class Handler:
_next_handler = None
def set_next(self, handler):
self._next_handler = handler
return handler
def handle(self, request):
if self._next_handler:
return self._next_handler.handle(request)
return None
class ConcreteHandler1(Handler):
def handle(self, request):
if request == "R1":
return f"ConcreteHandler1: Handled {request}"
else:
return super().handle(request)
class ConcreteHandler2(Handler):
def handle(self, request):
if request == "R2":
return f"ConcreteHandler2: Handled {request}"
else:
return super().handle(request)
# 使用
handler1 = ConcreteHandler1()
handler2 = ConcreteHandler2()
handler1.set_next(handler2)
print(handler1.handle("R2"))
适用场景:当你想让多个对象有机会处理单个请求时,从而解耦发送者和接收者;当你想让接收者不明确时。
优点:降低耦合度。它将请求的发送者和接收者解耦;简化了对象。使得对象不需要知道链的结构;增强了给对象指派职责的灵活性。通过改变链内的成员或调动它们的次序,允许动态地新增或删除责任。
缺点:不能保证请求一定被接收;系统性能将受到一定影响,而且在某些情况下会引起循环调用。
访问者模式(Visitor)
访问者模式是一种将算法与对象结构分离的软件设计模式。这种分离的实际效果是能够在不修改现有对象结构的情况下,向对象结构中添加新的操作。
class ConcreteComponentA:
def accept(self, visitor):
visitor.visit_concrete_component_a(self)
def exclusive_method_of_concrete_component_a(self):
return "A"
class ConcreteComponentB:
def accept(self, visitor):
visitor.visit_concrete_component_b(self)
def special_method_of_concrete_component_b(self):
return "B"
class Visitor:
def visit_concrete_component_a(self, element):
pass
def visit_concrete_component_b(self, element):
pass
class ConcreteVisitor1(Visitor):
def visit_concrete_component_a(self, element):
print(f"{element.exclusive_method_of_concrete_component_a()} + ConcreteVisitor1")
def visit_concrete_component_b(self, element):
print(f"{element.special_method_of_concrete_component_b()} + ConcreteVisitor1")
class ConcreteVisitor2(Visitor):
def visit_concrete_component_a(self, element):
print(f"{element.exclusive_method_of_concrete_component_a()} + ConcreteVisitor2")
def visit_concrete_component_b(self, element):
print(f"{element.special_method_of_concrete_component_b()} + ConcreteVisitor2")
# 使用
components = [ConcreteComponentA(), ConcreteComponentB()]
visitor1 = ConcreteVisitor1()
for component in components:
component.accept(visitor1)
visitor2 = ConcreteVisitor2()
for component in components:
component.accept(visitor2)
适用场景:当你需要对一个复杂对象结构(例如对象树)中的所有元素执行操作时;当你需要对一个对象结构中的元素进行很多不同且不相关的操作,而你想避免让这些操作“污染”这些元素的类时。
优点:符合单一职责原则;优秀的扩展性;将算法与对象结构分离。
缺点:增加了系统的复杂度;具体元素对访问者公布细节,违反了迪米特法则。
备忘录模式(Memento)
备忘录模式是一种软件设计模式,它提供了恢复对象到之前状态的能力(撤销通过rollback操作)。备忘录模式使用三个类对象:发起人、备忘录和看护者,以保存对象的状态。
class Originator:
_state = None
def __init__(self, state):
self._state = state
print(f"Originator: My initial state is: {self._state}")
def do_something(self):
print("Originator: I'm doing something important.")
self._state = self.generate_random_string(30)
print(f"Originator: and my state has changed to: {self._state}")
def generate_random_string(self, length=10):
import random
return ''.join(random.choices('abcdefghijklmnopqrstuvwxyz', k=length))
def save(self):
return ConcreteMemento(self._state)
def restore(self, memento):
self._state = memento.get_state()
print(f"Originator: My state has changed to: {self._state}")
class Memento:
def get_state(self):
pass
class ConcreteMemento(Memento):
_state = None
def __init__(self, state):
self._state = state
def get_state(self):
return self._state
class Caretaker:
_mementos = []
def __init__(self, originator):
self._originator = originator
def backup(self):
print("\nCaretaker: Saving Originator's state...")
self._mementos.append(self._originator.save())
def undo(self):
if not len(self._mementos):
return
memento = self._mementos.pop()
print(f"Caretaker: Restoring state to: {memento.get_state()}")
try:
self._originator.restore(memento)
except Exception:
self.undo()
# 使用
originator = Originator("Super-duper-super-puper-super.")
caretaker = Caretaker(originator)
caretaker.backup()
originator.do_something()
caretaker.backup()
originator.do_something()
caretaker.undo()
caretaker.undo()
适用场景:当你需要创建对象状态的快照以便稍后可以恢复对象到该状态时;当直接获取对象的状态会暴露实现细节并破坏对象的封装性时。
优点:可以在不破坏对象封装性的前提下捕获和恢复对象的内部状态;可以简化发起人的代码。
缺点:如果客户端过于频繁地创建备忘录,程序将消耗大量内存。
迭代器模式(Iterator)
迭代器模式提供了一种方法顺序访问一个聚合对象中各个元素,而又无需暴露该对象的内部表示。
class Iterator:
def has_next(self):
pass
def next(self):
pass
class ConcreteIterator(Iterator):
_position = None
_list = None
def __init__(self, list):
self._list = list
self._position = 0
def has_next(self):
return self._position < len(self._list)
def next(self):
if self.has_next():
item = self._list[self._position]
self._position += 1
return item
else:
return None
class Aggregate:
def iterator(self):
pass
class ConcreteAggregate(Aggregate):
_list = None
def __init__(self, list):
self._list = list
def iterator(self):
return ConcreteIterator(self._list)
# 使用
aggregate = ConcreteAggregate(["Red", "Green", "Blue"])
iterator = aggregate.iterator()
while iterator.has_next():
item = iterator.next()
print(item)
适用场景:当你的集合对象有复杂的数据结构,且你希望隐藏其复杂性,让客户代码透过一个简单的接口访问该集合时;当你需要对集合对象有多种遍历方式时。
优点:支持对集合对象的多种遍历;迭代器简化了聚合类;在同一个聚合上可以有多个遍历。
缺点:对于比较简单的聚合结构,使用迭代器模式可能会增加不必要的复杂性。
模板方法模式(Template Method)
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
class AbstractClass:
def template_method(self):
self.base_operation1()
self.required_operations1()
self.base_operation2()
self.hook1()
self.required_operations2()
self.base_operation3()
self.hook2()
# These operations already have implementations.
def base_operation1(self):
print("AbstractClass says: I am doing the bulk of the work")
def base_operation2(self):
print("AbstractClass says: But I let subclasses override some operations")
def base_operation3(self):
print("AbstractClass says: But I am doing the bulk of the work anyway")
# These operations have to be implemented in subclasses.
def required_operations1(self):
pass
def required_operations2(self):
pass
# These are "hooks." Subclasses may override them, but it's not mandatory
# since the hooks already have default (but empty) implementation.
def hook1(self):
pass
def hook2(self):
pass
class ConcreteClass1(AbstractClass):
def required_operations1(self):
print("ConcreteClass1 says: Implemented Operation1")
def required_operations2(self):
print("ConcreteClass1 says: Implemented Operation2")
class ConcreteClass2(AbstractClass):
def required_operations1(self):
print("ConcreteClass2 says: Implemented Operation1")
def required_operations2(self):
print("ConcreteClass2 says: Implemented Operation2")
def hook1(self):
print("ConcreteClass2 says: Overridden Hook1")
# 使用
concrete_class1 = ConcreteClass1()
concrete_class1.template_method()
concrete_class2 = ConcreteClass2()
concrete_class2.template_method()
适用场景:当你要一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现时;当你有多个类包含几乎相同的算法,但有些细节在各个类中的实现不同时。
优点:可以让客户端重用一个算法的框架,而不用与它的特定实现代码相耦合;可以将算法的核心部分放在一个地方,从而避免代码重复。
缺点:由于模板方法模式基于继承,所以它可能会导致更高层次的复杂性;可能会导致违反里氏替换原则,因为子类必须实现父类的抽象方法。
解释器模式(Interpreter)
解释器模式提供了评估语言的语法或表达式的方式,用于定义一个表示语言语法的方式,以及一个解释器,通过使用该表示来解释语言中的句子。
class AbstractExpression:
def interpret(self, context):
pass
class TerminalExpression(AbstractExpression):
def interpret(self, context):
print(f"Terminal for {context}")
class NonTerminalExpression(AbstractExpression):
def interpret(self, context):
print(f"NonTerminal for {context}")
class Context:
def __init__(self, input):
self.input = input
# 使用
context = Context("Context for interpretation")
terminal = TerminalExpression()
non_terminal = NonTerminalExpression()
terminal.interpret(context.input)
non_terminal.interpret(context.input)
适用场景:当有一个语言需要解释执行,并且你可以将该语言中的句子表示为一个抽象语法树时;当某些重复出现的问题可以用一种简单的语言来进行表达时。
优点:易于改变和扩展文法;通过改变解释器可以改变或扩展行为;复杂的文法可以分解成简单的子问题,这些子问题由相应的类解决。
缺点:当文法规则数目增加时,增加了系统的复杂度;增加了解释程序的执行开销。
空对象模式(Null Object)
空对象模式提供了一个无操作的对象实例来代替null。这样可以减少对null检查的需要,可以用来提供默认的行为。
class AbstractObject:
def request(self):
pass
class RealObject(AbstractObject):
def request(self):
print("RealObject: Handling request.")
class NullObject(AbstractObject):
def request(self):
pass # Do nothing
def get_object(key):
"""Factory method to get an object"""
if key == "real":
return RealObject()
return NullObject()
# 使用
obj = get_object("real")
obj.request()
obj = get_object("null")
obj.request() # Nothing happens, but no null check is needed
适用场景:当你需要提供一个无操作的默认行为时;当你想避免在代码中频繁检查null值时。
优点:减少了对null检查的需要,可以提供默认的行为。
缺点:可能会隐藏错误,因为它们不再导致null指针异常。
服务定位器模式(Service Locator)
服务定位器模式用于解耦应用程序的服务消费者和具体的服务实现。它使用一个中央注册表(也称为“服务定位器”),这个注册表负责提供服务实例的查找和缓存。
class Service:
def execute(self):
pass
class Service1(Service):
def execute(self):
print("Executing Service1")
class Service2(Service):
def execute(self):
print("Executing Service2")
class ServiceLocator:
_cache = {}
@staticmethod
def get_service(service_name):
service = ServiceLocator._cache.get(service_name)
if service:
return service
if service_name == "Service1":
service = Service1()
ServiceLocator._cache[service_name] = service
return service
elif service_name == "Service2":
service = Service2()
ServiceLocator._cache[service_name] = service
return service
return None
# 使用
service = ServiceLocator.get_service("Service1")
service.execute()
service = ServiceLocator.get_service("Service1")
service.execute()
适用场景:当你想隐藏服务的实例化逻辑并统一管理服务实例时;当你需要灵活地更换和配置服务时。
优点:减少了客户端和服务之间的耦合;提供了服务的查找和缓存机制。
缺点:如果过度使用,可能会导致代码难以追踪和调试;可能会引入全局状态,使得系统变得复杂。
观察者模式(Observer)
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
适用场景:当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少对象有待改变时。
优点:支持简单的广播通信,自动通知所有已订阅的对象。
缺点:如果订阅者很多,通知的过程可能会很慢。
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self):
for observer in self._observers:
observer.update(self)
class Observer:
def update(self, subject):
pass
class ConcreteSubject(Subject):
_state = None
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify()
class ConcreteObserver(Observer):
def update(self, subject):
print("Observer: Subject's state changed to", subject.state)
# 使用
subject = ConcreteSubject()
observer_a = ConcreteObserver()
subject.attach(observer_a)
subject.state = "state 1"
策略模式(Strategy)
定义一系列的算法,把它们一个个封装起来,并使它们可相互替换。
适用场景:当你想使用不同的算法来完成某个特定任务时。它允许在运行时选择最适合的算法。
优点:可以切换算法或策略,算法可以独立于使用它们的客户端变化。
缺点:如果策略很多,管理和维护各个策略之间的关系可能会复杂。
class Strategy:
def do_algorithm(self, data):
pass
class ConcreteStrategyA(Strategy):
def do_algorithm(self, data):
return sorted(data)
class ConcreteStrategyB(Strategy):
def do_algorithm(self, data):
return reversed(sorted(data))
class Context:
_strategy = None
def __init__(self, strategy):
self._strategy = strategy
def set_strategy(self, strategy):
self._strategy = strategy
def do_some_business_logic(self):
result = self._strategy.do_algorithm(["a", "b", "c", "d", "e"])
print(",".join(result))
# 使用
context = Context(ConcreteStrategyA())
context.do_some_business_logic()
context.set_strategy(ConcreteStrategyB())
context.do_some_business_logic()
适配器模式(Adapter)
允许将一个类的接口转换成客户期望的另一个接口,使原本接口不兼容的类可以一起工作。
适用场景:当希望使用某个类,但其接口与其他代码不兼容时。
优点:可以让任何两个没有关联的类一起运行。
缺点:增加了系统的复杂性。
class Target:
def request(self):
return "Target's default behavior."
class Adaptee:
def specific_request(self):
return ".eetpadA eht fo roivaheb laicepS"
class Adapter(Target, Adaptee):
def request(self):
return f"Adapter: (TRANSLATED) {self.specific_request()[::-1]}"
# 使用
target = Target()
print(target.request())
adapter = Adapter()
print(adapter.request())
装饰器模式(Decorator)
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。
适用场景:当不改变对象的结构情况下,动态地给一个对象增加一些额外的职责时。
优点:比继承更灵活,避免在层次结构高的层次中有太多的类。
缺点:会增加许多小对象,增加了系统的复杂性。
class Component:
def operation(self):
pass
class ConcreteComponent(Component):
def operation(self):
return "ConcreteComponent"
class Decorator(Component):
_component = None
def __init__(self, component):
self._component = component
def operation(self):
return self._component.operation()
class ConcreteDecoratorA(Decorator):
def operation(self):
return f"ConcreteDecoratorA({self._component.operation()})"
# 使用
simple = ConcreteComponent()
decorated = ConcreteDecoratorA(simple)
print(decorated.operation())
桥接模式(Bridge)
将抽象部分与实现部分分离,使它们可以独立变化。通过组合的方式建立两个类层次结构:一个负责抽象的接口,另一个负责具体的实现。
适用场景:当一个类存在两个独立变化的维度时,通过组合的方式让这两个维度可以独立进行扩展。当你想避免抽象和实现之间的永久绑定时;当类的抽象以及它的实现都应该通过生成子类的方式进行扩展时。
优点:提高了系统的可扩展性和灵活性。分离接口及其实现部分。
缺点:增加了系统的理解与设计难度,以及系统的复杂度。
class ImplementationInterface:
def method(self):
pass
class ConcreteImplementationA(ImplementationInterface):
def method(self):
print("ConcreteImplementation A method")
class ConcreteImplementationB(ImplementationInterface):
def method(self):
print("ConcreteImplementation B method")
class Abstraction:
def __init__(self, implementation):
self.implementation = implementation
def operation(self):
self.implementation.method()
# 使用
implementation = ConcreteImplementationA()
abstraction = Abstraction(implementation)
abstraction.operation()
implementation = ConcreteImplementationB()
abstraction = Abstraction(implementation)
abstraction.operation()
组合模式(Composite)
将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
适用场景:当您希望客户端忽略组合对象与单个对象的差异时;当您希望统一对待树形结构中的所有对象时。
优点:可以清楚地定义层次结构,使得操作和管理子对象更加简单。
缺点:设计较为复杂,客户端需要花更多时间理解。
class Component:
def add(self, component):
pass
def remove(self, component):
pass
def operation(self):
pass
class Leaf(Component):
def operation(self):
print("Leaf operation")
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):
for child in self._children:
child.operation()
# 使用
leaf = Leaf()
composite = Composite()
composite.add(leaf)
composite.operation()
代理模式(Proxy)
为其他对象提供一种代理以控制对这个对象的访问。
适用场景:当您想在访问对象时执行一些操作,如安全控制、延迟初始化等。
优点:可以在不修改被代理对象的情况下进行一些额外的操作。
缺点:可能会导致系统设计变得复杂。
class Subject:
def request(self):
pass
class RealSubject(Subject):
def request(self):
print("RealSubject: Handling request.")
class Proxy(Subject):
def __init__(self, real_subject):
self._real_subject = real_subject
def request(self):
if self.check_access():
self._real_subject.request()
self.log_access()
def check_access(self):
print("Proxy: Checking access prior to firing a real request.")
return True
def log_access(self):
print("Proxy: Logging the time of request.")
# 使用
real_subject = RealSubject()
proxy = Proxy(real_subject)
proxy.request()
命令模式(Command)
将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
适用场景:当你需要参数化对象根据请求执行操作时;当需要提供操作的撤销和恢复功能时。
优点:降低系统耦合度;新的命令可以很容易地加入到系统中。
缺点:可能会导致某些系统有过多的具体命令类。
class Command:
def execute(self):
pass
class Light:
def on(self):
print("Light is on")
def off(self):
print("Light is off")
class LightOnCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.on()
class LightOffCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.off()
class RemoteControl:
def submit(self, command):
command.execute()
# 使用
light = Light()
light_on = LightOnCommand(light)
light_off = LightOffCommand(light)
remote = RemoteControl()
remote.submit(light_on)
remote.submit(light_off)
状态模式(State)
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
适用场景:当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时。
优点:封装了转换规则;枚举可能的状态,在枚举状态之前将所有与状态相关的行为放到各个状态类中。
缺点:如果状态多,逻辑分散各个状态类,导致状态类膨胀。
class State:
def handle(self, context):
pass
class ConcreteStateA(State):
def handle(self, context):
print("Turning to state B")
context.state = ConcreteStateB()
class ConcreteStateB(State):
def handle(self, context):
print("Turning to state A")
context.state = ConcreteStateA()
class Context:
state = None
def __init__(self, state):
self.state = state
def request(self):
self.state.handle(self)
# 使用
context = Context(ConcreteStateA())
context.request() # Turning to state B
context.request() # Turning to state A
中介者模式(Mediator)
通过引入一个中介者对象来简化多个对象间的通信。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
适用场景:当一组对象以定义良好但复杂的方式进行通信时;重用一个对象很困难,因为它引用了许多其他对象并与之通信时。
优点:减少了类之间的依赖,把一对多的依赖变成了一对一的依赖。
缺点:中介者可能会变得过于复杂,从而变成一个“上帝对象”。
class Mediator:
def notify(self, sender, event):
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("Mediator reacts on A and triggers following operations:")
self._component2.do_c()
elif event == "D":
print("Mediator reacts on D and triggers following operations:")
self._component1.do_b()
class BaseComponent:
def __init__(self, mediator=None):
self._mediator = mediator
@property
def mediator(self):
return self._mediator
@mediator.setter
def mediator(self, mediator):
self._mediator = mediator
class Component1(BaseComponent):
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):
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)
c1.do_a()
c2.do_d()
备忘录模式(Memento)
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后将对象恢复到原先保存的状态。
适用场景:需要保存一个对象在某一个时刻的状态或部分状态,这样以后就可以恢复到先前的状态。
优点:提供了一种恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
缺点:资源消耗较大,每保存一次状态都需要消耗一定的系统资源。
class Memento:
def __init__(self, state):
self._state = state
def get_state(self):
return self._state
class Originator:
_state = ""
def set_state(self, state):
self._state = state
def get_state(self):
return self._state
def save_state_to_memento(self):
return Memento(self._state)
def get_state_from_memento(self, memento):
self._state = memento.get_state()
class Caretaker:
_memento_list = []
def add(self, state):
self._memento_list.append(state)
def get(self, index):
return self._memento_list[index]
# 使用
originator = Originator()
caretaker = Caretaker()
originator.set_state("State #1")
originator.set_state("State #2")
caretaker.add(originator.save_state_to_memento())
originator.set_state("State #3")
caretaker.add(originator.save_state_to_memento())
originator.set_state("State #4")
print("Current State: " + originator.get_state())
saved_state = caretaker.get(0)
originator.get_state_from_memento(saved_state)
print("First saved State: " + originator.get_state())
saved_state = caretaker.get(1)
originator.get_state_from_memento(saved_state)
print("Second saved State: " + originator.get_state())
迭代器模式(Iterator)
提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露其内部的表示。
适用场景:当你需要访问一个聚合对象的内容而无需暴露其内部表示时;支持对聚合对象的多种遍历。
优点:支持多种遍历方式;简化了聚合类。
缺点:对于比较简单的遍历(如在列表上的遍历),使用迭代器模式可能会略显复杂。
class Iterator:
def has_next(self):
pass
def next(self):
pass
class ConcreteIterator(Iterator):
def __init__(self, aggregate):
self._aggregate = aggregate
self._index = 0
def has_next(self):
return self._index < len(self._aggregate)
def next(self):
if self.has_next():
ret = self._aggregate[self._index]
self._index += 1
return ret
else:
return None
class Aggregate:
def iterator(self):
pass
class ConcreteAggregate(Aggregate):
def __init__(self):
self._items = []
def add(self, value):
self._items.append(value)
def iterator(self):
return ConcreteIterator(self._items)
# 使用
aggregate = ConcreteAggregate()
aggregate.add("Item 1")
aggregate.add("Item 2")
aggregate.add("Item 3")
iterator = aggregate.iterator()
while iterator.has_next():
item = iterator.next()
print(item)
解释器模式(Interpreter)
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用场景:当有一个语言需要解释执行,并且你可以将该语言中的句子表示为一个抽象语法树时。
优点:易于改变和扩展文法。
缺点:对于复杂的文法,难以维护。
class AbstractExpression:
def interpret(self, context):
pass
class TerminalExpression(AbstractExpression):
def interpret(self, context):
print("Terminal for", context)
class NonterminalExpression(AbstractExpression):
def interpret(self, context):
print("Nonterminal for", context)
class Context:
pass
# 使用
context = Context()
terminal = TerminalExpression()
nonterminal = NonterminalExpression()
terminal.interpret(context)
nonterminal.interpret(context)
外观模式(Facade)
提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,使得子系统更容易使用。
适用场景:当你要为一个复杂子系统提供一个简单接口时;当客户端与多个子系统之间存在很大的依赖性时。
优点:减少系统相互依赖,提高了灵活性和安全性。
缺点:不符合开闭原则,修改外观类需要修改其所有客户端的代码。
class Subsystem1:
def operation1(self):
return "Subsystem1: Ready!\n"
def operationN(self):
return "Subsystem1: Go!\n"
class Subsystem2:
def operation1(self):
return "Subsystem2: Get ready!\n"
def operationZ(self):
return "Subsystem2: Fire!\n"
class Facade:
def __init__(self):
self._subsystem1 = Subsystem1()
self._subsystem2 = Subsystem2()
def operation(self):
results = "Facade initializes subsystems:\n"
results += self._subsystem1.operation1()
results += self._subsystem2.operation1()
results += "Facade orders subsystems to perform the action:\n"
results += self._subsystem1.operationN()
results += self._subsystem2.operationZ()
return results
# 使用
facade = Facade()
print(facade.operation())
享元模式(Flyweight)
运用共享技术有效地支持大量细粒度的对象。
适用场景:当应用程序使用了大量的对象,这些对象造成了很大的存储开销时;对象的大多数状态都可以变为外部状态。
优点:大大减少对象的创建,降低系统的内存使用,增强程序的性能。
缺点:使系统更加复杂,需要分离内部状态和外部状态,使得编程逻辑复杂化。
class Flyweight:
def operation(self, extrinsic_state):
pass
class ConcreteFlyweight(Flyweight):
def __init__(self, intrinsic_state):
self.intrinsic_state = intrinsic_state
def operation(self, extrinsic_state):
print(f"ConcreteFlyweight: Intrinsic({self.intrinsic_state}) and Extrinsic({extrinsic_state}) state")
class FlyweightFactory:
_flyweights = {}
def get_flyweight(self, key):
if not key in self._flyweights:
self._flyweights[key] = ConcreteFlyweight(key)
return self._flyweights[key]
# 使用
factory = FlyweightFactory()
flyweight = factory.get_flyweight("a")
flyweight.operation("1")
flyweight = factory.get_flyweight("b")
flyweight.operation("2")
责任链模式(Chain of Responsibility)
为请求创建一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。
适用场景:当程序需要处理不同类型的请求,且请求的类型和顺序预先不确定时;当必须通过多个对象来处理请求时。
优点:降低耦合度。它将请求的发送者和接收者解耦。
缺点:请求不保证被接收(可能一个请求最终未被任何对象处理);调试复杂度增加。
class Handler:
def __init__(self, successor=None):
self._successor = successor
def handle_request(self, request):
if self._successor:
self._successor.handle_request(request)
class ConcreteHandler1(Handler):
def handle_request(self, request):
if 0 < request <= 10:
print(f"Request {request} handled in handler 1")
else:
super().handle_request(request)
class ConcreteHandler2(Handler):
def handle_request(self, request):
if 10 < request <= 20:
print(f"Request {request} handled in handler 2")
else:
super().handle_request(request)
# 使用
handler1 = ConcreteHandler1()
handler2 = ConcreteHandler2(successor=handler1)
requests = [2, 5, 14, 22, 18, 3, 27, 20]
for request in requests:
handler2.handle_request(request)
访问者模式(Visitor)
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
适用场景:当一个对象结构包含很多类对象,且你想对这些对象施加一些依赖于其具体类的操作时;当需要对一个复杂的对象结构进行很多不同且不相关的操作时,为避免“污染”这些类,可以使用访问者模式。
优点:增加新的操作很容易,因为增加新的操作意味着增加一个新的访问者。
缺点:增加新的元素类变得困难。
class Element:
def accept(self, visitor):
pass
class ConcreteElementA(Element):
def accept(self, visitor):
visitor.visit_concrete_element_a(self)
def operation_a(self):
return "ConcreteElementA"
class ConcreteElementB(Element):
def accept(self, visitor):
visitor.visit_concrete_element_b(self)
def operation_b(self):
return "ConcreteElementB"
class Visitor:
def visit_concrete_element_a(self, element):
pass
def visit_concrete_element_b(self, element):
pass
class ConcreteVisitor1(Visitor):
def visit_concrete_element_a(self, element):
print(f"{element.operation_a()} visited by ConcreteVisitor1")
def visit_concrete_element_b(self, element):
print(f"{element.operation_b()} visited by ConcreteVisitor1")
# 使用
elements = [ConcreteElementA(), ConcreteElementB()]
visitor1 = ConcreteVisitor1()
for element in elements:
element.accept(visitor1)
模板方法模式(Template Method)
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
适用场景:当你有多个类包含几乎相同的方法,但有轻微的差异时;当你想要控制子类扩展时。
优点:可以让子类在不改变算法结构的情况下,重新定义算法中的某些步骤。
缺点:对于每个不同的实现,你需要一个子类,这可能导致类的数量增加,使系统更加庞大。
from abc import ABC, abstractmethod
class AbstractClass(ABC):
def template_method(self):
self.base_operation1()
self.required_operations1()
self.base_operation2()
self.hook1()
self.required_operations2()
self.base_operation3()
self.hook2()
def base_operation1(self):
print("AbstractClass says: I am doing the bulk of the work")
def base_operation2(self):
print("AbstractClass says: But I let subclasses override some operations")
def base_operation3(self):
print("AbstractClass says: But I am doing the bulk of the work anyway")
@abstractmethod
def required_operations1(self):
pass
@abstractmethod
def required_operations2(self):
pass
def hook1(self):
pass
def hook2(self):
pass
class ConcreteClass1(AbstractClass):
def required_operations1(self):
print("ConcreteClass1 says: Implemented Operation1")
def required_operations2(self):
print("ConcreteClass1 says: Implemented Operation2")
def hook1(self):
print("ConcreteClass1 says: Overridden Hook1")
# 使用
concrete_class = ConcreteClass1()
concrete_class.template_method()
策略模式(Strategy)
定义一系列算法,把它们一个个封装起来,并使它们可互相替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。
适用场景:当你想使用不同的算法来完成某个特定任务时;当你有很多类似的类,但它们执行某些行为的方式不同时。
优点:可以切换算法或策略;可以避免使用多重条件转移语句;扩展性良好。
缺点:客户端必须知道所有的策略类,并自行决定使用哪一个策略类;产生很多策略类。
class Strategy(ABC):
@abstractmethod
def do_algorithm(self, data):
pass
class ConcreteStrategyA(Strategy):
def do_algorithm(self, data):
return sorted(data)
class ConcreteStrategyB(Strategy):
def do_algorithm(self, data):
return reversed(sorted(data))
class Context:
def __init__(self, strategy: Strategy):
self._strategy = strategy
@property
def strategy(self):
return self._strategy
@strategy.setter
def strategy(self, strategy):
self._strategy = strategy
def do_some_business_logic(self):
result = self._strategy.do_algorithm(["a", "b", "c", "d", "e"])
print(",".join(result))
# 使用
context = Context(ConcreteStrategyA())
context.do_some_business_logic()
context.strategy = ConcreteStrategyB()
context.do_some_business_logic()
状态模式(State)再次概述
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
适用场景:当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时;当代码中包含大量与对象状态有关的条件语句时。
优点:将所有与某个状态相关的行为都放入一个对象中,通过将状态抽象化,可以将操作和状态分离,使得增加新状态变得更简单。
缺点:如果状态多,会导致有很多状态类,系统变得复杂。
两阶段提交(Two-phase Commit)
两阶段提交协议是一种保证分布式系统中事务一致性的协议,它将事务提交过程分为两个阶段来进行。
适用场景:需要在分布式系统中保持跨多个节点的事务一致性时。
优点:可以在分布式系统中保持事务的ACID特性。
缺点:性能开销较大,因为需要多次网络通信;在某些阶段出现故障时,可能会导致系统锁定,等待恢复。
解释器模式(Interpreter)
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用场景:当有一个语言需要解释执行,并且可以将该语言中的句子表示为一个抽象语法树时。常用于SQL解析、符号处理引擎等。
优点:易于改变和扩展文法。因为解释器使用类来表示文法规则,你可以使用继承来改变或扩展该文法。
缺点:对于复杂的文法,难以维护。解释器模式会引起类膨胀,每个文法都需要创建一个类,对于复杂的文法,维护起来非常困难。
服务定位器模式(Service Locator)
用来解耦客户端和服务之间的关系。通过一个中央注册处来获取服务,客户端不需要知道服务的具体实现。
适用场景:当需要解耦应用程序的各个部分时,特别是在实现服务注入时,服务定位器可以作为依赖注入的一种替代方法。
优点:减少了客户端和服务之间的耦合。
缺点:如果过度使用,可能会导致代码难以追踪和调试,因为依赖关系的创建被隐藏在了服务定位器内部。