文章目录
- 策略模式
- 场景
- 示例
- 迭代器模式
- 场景
- 示例
- 访问者模式
- 场景
- 示例
- 观察者模式
- 场景
- 示例
- 命令模式
- 场景
- 示例
- 模板方法模式
- 场景
- 示例
- 模板方法模式
- 场景
- 示例
- 事件驱动模式
- 场景
- 示例
- 责任链模式
- 场景
- 示例
- 中介者模式
- 场景
- 示例
- 状态模式
- 场景
- 示例
策略模式
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互相替换。策略模式使得算法可以独立于客户端而变化,客户端可以根据需要选择不同的算法。
-
策略(Strategy):定义了一个算法族的抽象接口,所有具体策略类都实现了这个接口。
-
具体策略(Concrete Strategy):实现了策略接口的具体算法。
-
上下文(Context):维护一个对策略对象的引用,并提供一个接口来设置和切换策略。上下文通过委托给策略对象来执行算法。
场景
-
行为多样化:当一个类有多个行为或算法,并且这些行为可以根据不同的需求进行切换时,可以使用策略模式。策略模式将每个行为封装成一个策略对象,客户端可以根据需要选择和切换不同的策略。
-
条件语句复杂:当一个类中包含大量的条件语句来选择不同的行为时,可以使用策略模式来简化代码。策略模式将每个条件语句对应的行为封装成一个策略对象,客户端只需要根据需要选择和使用策略,而无需关心具体的实现细节。
-
算法可自由切换:当一个类的行为或算法可能需要在运行时动态切换时,可以使用策略模式。策略模式允许客户端在不影响原有代码的情况下动态选择和切换不同的策略,提高了代码的灵活性和可维护性。
-
需要对算法进行封装:当需要对算法进行封装,使其可以独立于客户端而变化时,可以使用策略模式。策略模式将算法封装成独立的策略对象,客户端只需要关注选择和使用策略的接口,而无需关心具体的算法实现细节。
-
排序算法:当需要对一组数据进行排序时,可以根据不同的需求选择不同的排序算法,如快速排序、冒泡排序、插入排序等。
-
数据校验:当需要对用户输入的数据进行校验时,可以根据不同的校验规则选择不同的校验算法,如邮箱校验、手机号校验、密码强度校验等。
-
商业规则引擎:当需要根据不同的商业规则对业务逻辑进行处理时,可以根据不同的规则选择不同的处理策略,如折扣策略、促销策略、会员等级策略等。
示例
# 定义策略接口
class PaymentStrategy:def pay(self, amount):pass# 具体策略类:支付宝支付
class AliPayStrategy(PaymentStrategy):def pay(self, amount):print(f"支付宝支付:¥{amount}")# 具体策略类:微信支付
class WeChatPayStrategy(PaymentStrategy):def pay(self, amount):print(f"微信支付:¥{amount}")# 具体策略类:银行卡支付
class CardPayStrategy(PaymentStrategy):def pay(self, amount):print(f"银行卡支付:¥{amount}")# 上下文类
class PaymentContext:def __init__(self, payment_strategy):self._payment_strategy = payment_strategydef set_payment_strategy(self, payment_strategy):self._payment_strategy = payment_strategydef pay(self, amount):self._payment_strategy.pay(amount)# 客户端代码
def main():# 创建支付上下文对象payment_context = PaymentContext(AliPayStrategy())# 进行支付payment_context.pay(100)# 切换支付策略为微信支付payment_context.set_payment_strategy(WeChatPayStrategy())payment_context.pay(200)# 切换支付策略为银行卡支付payment_context.set_payment_strategy(CardPayStrategy())payment_context.pay(300)if __name__ == "__main__":main()
- 输出结果
支付宝支付:¥100
微信支付:¥200
银行卡支付:¥300
迭代器模式
迭代器模式(Iterator Pattern)是一种行为设计模式,它用于提供一种方法来顺序访问聚合对象中的元素,而不需要暴露聚合对象的内部表示。迭代器模式将迭代逻辑封装在一个单独的迭代器对象中,使得客户端可以通过统一的接口来遍历聚合对象,而无需了解其内部结构。
-
迭代器(Iterator):定义了访问和遍历聚合对象元素的接口,包括 iter 方法和 next 方法。
-
具体迭代器(Concrete Iterator):实现了迭代器接口,负责管理遍历聚合对象中的元素。
-
聚合对象(Aggregate):定义了一个接口来创建相应的迭代器对象。
-
具体聚合对象(Concrete Aggregate):实现了聚合对象接口,负责创建具体的迭代器对象,并提供了一个方法来获取迭代器。
场景
-
遍历集合对象:当需要遍历聚合对象中的元素时,并且希望遍历逻辑可以独立于聚合对象和客户端而变化时,可以使用迭代器模式。迭代器模式将遍历逻辑封装在一个迭代器对象中,使得客户端可以通过统一的接口来遍历不同类型的聚合对象。
-
隐藏聚合对象内部结构:当希望隐藏聚合对象的内部结构,并且通过迭代器来访问聚合对象中的元素时,可以使用迭代器模式。迭代器模式将遍历逻辑和聚合对象的内部结构解耦,使得客户端不需要了解聚合对象的具体实现细节。
-
支持多种遍历方式:当需要支持多种遍历方式,并且希望遍历逻辑可以独立变化时,可以使用迭代器模式。迭代器模式可以定义多个不同的迭代器对象,每个迭代器对象负责不同的遍历方式,客户端可以根据需要选择合适的迭代器对象来遍历聚合对象。
-
简化客户端代码:当希望简化客户端代码,并且使客户端不需要了解聚合对象的具体实现细节时,可以使用迭代器模式。迭代器模式将遍历逻辑封装在迭代器对象中,客户端只需要通过统一的接口来遍历聚合对象,简化了客户端代码。
-
集合类的迭代器:迭代器模式常用于集合类中,如列表、字典、集合等。通过迭代器模式,可以在不暴露集合类内部结构的情况下遍历集合中的元素。
-
文件流的迭代器:迭代器模式可以用于文件流中,如文本文件、日志文件等。通过迭代器模式,可以逐行读取文件内容,而不需要一次性加载整个文件到内存中。
-
数据库查询结果的迭代器:迭代器模式可以用于数据库查询结果中,如查询结果集合中的行数据。通过迭代器模式,可以逐行遍历查询结果集合中的数据,而不需要一次性加载整个结果集合到内存中。
示例
# 定义迭代器接口
class Iterator:def __iter__(self):passdef __next__(self):pass# 具体迭代器类:顺序迭代器
class SequentialIterator(Iterator):def __init__(self, collection):self._collection = collectionself._index = 0def __iter__(self):return selfdef __next__(self):if self._index < len(self._collection):item = self._collection[self._index]self._index += 1return itemelse:raise StopIteration# 客户端代码
def main():collection = [1, 2, 3, 4, 5]# 创建顺序迭代器iterator = SequentialIterator(collection)# 使用迭代器遍历集合for item in iterator:print(item)if __name__ == "__main__":main()
- 输出结果
1
2
3
4
5
访问者模式
访问者模式(Visitor Pattern)是一种行为设计模式,它用于在不改变元素类的前提下定义对元素类中的各个元素进行操作的新操作。访问者模式通过在元素类中添加一个接受访问者对象的方法,并在访问者对象中定义对元素类中各个元素进行操作的方法,使得可以在不改变元素类的情况下添加新的操作。
-
访问者(Visitor):定义了对元素类中各个元素进行操作的方法。访问者模式中通常会定义一个访问者接口,包含对各种类型的元素进行操作的方法。
-
具体访问者(Concrete Visitor):实现了访问者接口,负责实现对元素类中各个元素进行具体操作的方法。
-
元素(Element):定义了接受访问者对象的方法,并将自身传递给访问者对象。元素类中通常会包含一个接受访问者对象的方法,用于将自身传递给访问者对象。
-
具体元素(Concrete Element):实现了元素接口,负责实现接受访问者对象的方法,并将自身传递给访问者对象。具体元素类中通常会包含一个接受访问者对象的方法,并在方法中调用访问者对象的对应方法。
-
对象结构(Object Structure):包含一个元素的集合,并提供一个接受访问者对象的方法。对象结构类中通常会包含一个集合对象,并提供一个接受访问者对象的方法,用于将访问者对象应用到集合中的每个元素上。
场景
-
对象结构稳定,但操作频繁变化:当对象结构相对稳定,但需要对其进行各种不同的操作时,可以使用访问者模式。访问者模式将操作封装在访问者对象中,使得可以在不改变元素类的情况下定义新的操作,从而适应操作频繁变化的需求。
-
数据结构与数据操作分离:当数据结构与对数据的操作分离,且操作需要根据不同的数据结构而变化时,可以使用访问者模式。访问者模式将操作封装在访问者对象中,使得可以在不同的数据结构上应用相同的访问者对象,从而实现操作的复用。
-
执行复杂的操作:当需要对一个复杂对象结构中的各个元素进行不同的、复杂的操作时,可以使用访问者模式。访问者模式将操作封装在访问者对象中,使得可以对复杂的操作进行拆分和组合,提高了代码的可维护性和可扩展性。
-
添加新操作频繁:当需要添加新的操作时,但不希望修改元素类的情况下,可以使用访问者模式。访问者模式通过在访问者对象中定义新的操作方法,使得可以在不改变元素类的情况下新增操作,提高了系统的灵活性和可扩展性。
示例
from abc import ABC, abstractmethod# 抽象元素:元素
class Element(ABC):@abstractmethoddef accept(self, visitor):pass# 具体元素:圆形
class Circle(Element):def accept(self, visitor):visitor.visit_circle(self)# 具体元素:矩形
class Rectangle(Element):def accept(self, visitor):visitor.visit_rectangle(self)# 抽象访问者:访问者
class Visitor(ABC):@abstractmethoddef visit_circle(self, circle):pass@abstractmethoddef visit_rectangle(self, rectangle):pass# 具体访问者:面积计算器
class AreaCalculator(Visitor):def visit_circle(self, circle):print("计算圆形的面积")def visit_rectangle(self, rectangle):print("计算矩形的面积")# 客户端代码
def main():# 创建元素对象circle = Circle()rectangle = Rectangle()# 创建访问者对象并使用访问者访问元素area_calculator = AreaCalculator()circle.accept(area_calculator)rectangle.accept(area_calculator)if __name__ == "__main__":main()
- 输出结果
计算圆形的面积
计算矩形的面积
观察者模式
观察者模式(Observer Pattern)是一种行为设计模式,用于定义对象之间的一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。
在观察者模式中,主题(Subject)维护一个观察者(Observer)列表,每当主题的状态发生变化时,它会遍历观察者列表并通知每个观察者,使得观察者可以自动更新。观察者模式将主题和观察者解耦,使得主题和观察者可以独立变化,提高了代码的灵活性和可维护性。
-
主题(Subject):维护一个观察者列表,并提供方法来添加、删除和通知观察者。
-
具体主题(Concrete Subject):实现了主题接口,负责维护一个观察者列表,并在状态发生变化时通知观察者。
-
观察者(Observer):定义了一个更新接口,用于接收主题的通知并进行相应的更新。
-
具体观察者(Concrete Observer):实现了观察者接口,负责在接收到主题通知时进行相应的更新操作。
场景
-
GUI 应用程序中的事件处理:在图形用户界面(GUI)应用程序中,用户操作(如点击按钮、输入文本等)可以作为主题,而界面元素(如按钮、文本框等)可以作为观察者。当用户操作发生时,主题会通知所有观察者并更新界面。
-
消息通知系统:在消息通知系统中,消息发布者可以作为主题,而订阅者可以作为观察者。当有新消息发布时,主题会通知所有订阅者并发送消息。
-
股票市场监控系统:在股票市场监控系统中,股票价格变化可以作为主题,而投资者可以作为观察者。当股票价格发生变化时,主题会通知所有投资者并更新股票价格。
-
事件驱动的系统:在事件驱动的系统中,事件源可以作为主题,而事件监听器可以作为观察者。当事件发生时,主题会通知所有观察者并执行相应的事件处理逻辑。
-
发布-订阅模型:在发布-订阅模型中,发布者可以作为主题,而订阅者可以作为观察者。当有新的消息或事件发布时,主题会通知所有订阅者并执行相应的处理逻辑。
示例
from abc import ABC, abstractmethod# 抽象主题:主题
class Subject(ABC):@abstractmethoddef attach(self, observer):pass@abstractmethoddef detach(self, observer):pass@abstractmethoddef notify(self):pass# 具体主题:天气
class Weather(Subject):def __init__(self):self.observers = []self.temperature = 0self.humidity = 0def 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.temperature, self.humidity)def set_weather(self, temperature, humidity):self.temperature = temperatureself.humidity = humidityself.notify()# 抽象观察者:观察者
class Observer(ABC):@abstractmethoddef update(self, temperature, humidity):pass# 具体观察者:手机
class Phone(Observer):def update(self, temperature, humidity):print("手机收到天气通知:温度 {} 度,湿度 {}%".format(temperature, humidity))# 具体观察者:电视
class Television(Observer):def update(self, temperature, humidity):print("电视收到天气通知:当前天气情况,温度 {} 度,湿度 {}%".format(temperature, humidity))# 客户端代码
def main():# 创建天气主题对象weather = Weather()# 创建手机和电视观察者对象并注册到天气主题phone = Phone()television = Television()weather.attach(phone)weather.attach(television)# 设置天气情况并通知观察者weather.set_weather(28, 60)if __name__ == "__main__":main()
- 输出结果
手机收到天气通知:温度 28 度,湿度 60%
电视收到天气通知:当前天气情况,温度 28 度,湿度 60%
命令模式
命令模式(Command Pattern)是一种行为设计模式,它将请求封装成一个对象,从而允许使用不同的请求、队列或者日志请求来参数化其他对象,并且支持可撤销操作。
在命令模式中,客户端发送请求的对象称为调用者(Invoker),而接收和执行请求的对象称为接收者(Receiver)。命令模式将请求封装成一个命令对象(Command),并定义了一个统一的执行方法,使得调用者不需要知道请求的具体接收者,只需要知道如何执行命令。
-
命令(Command):定义了执行操作的接口,包含一个执行方法 execute,用于执行具体的操作。
-
具体命令(Concrete Command):实现了命令接口,负责将请求绑定到接收者并执行具体的操作。
-
接收者(Receiver):负责执行命令指定的操作。
-
调用者(Invoker):负责发送请求并执行命令。
-
客户端(Client):创建具体命令对象并将其绑定到调用者,然后通过调用者来发送请求。
场景
-
GUI 应用程序的菜单和工具栏:在图形用户界面(GUI)应用程序中,菜单和工具栏上的操作可以被封装成命令对象,当用户点击菜单或工具栏按钮时,相应的命令对象被执行,从而实现与接收者的解耦和可撤销操作。
-
多级撤销和重做:命令模式可以用于实现多级撤销和重做功能。每个命令对象都记录了执行操作和撤销操作的方法,通过将命令对象保存在历史记录中,可以轻松地支持多级撤销和重做。
-
数据库事务管理:在数据库系统中,事务操作可以被封装成命令对象。当事务提交时,命令对象被执行;当事务回滚时,命令对象被撤销。通过使用命令模式,可以实现数据库操作和事务管理的解耦。
-
网络请求处理:在网络应用程序中,网络请求可以被封装成命令对象。当网络请求到达时,相应的命令对象被创建并执行,从而实现与网络请求处理逻辑的解耦和可扩展性。
-
日程安排和任务调度:在日程安排和任务调度系统中,日程和任务可以被封装成命令对象。当日程或任务开始时,相应的命令对象被执行,从而实现与日程安排和任务调度逻辑的解耦和可撤销操作。
示例
from abc import ABC, abstractmethod# 命令接口
class Command(ABC):@abstractmethoddef execute(self):pass# 具体命令:开灯
class TurnOnCommand(Command):def __init__(self, light):self.light = lightdef execute(self):self.light.turn_on()# 具体命令:关灯
class TurnOffCommand(Command):def __init__(self, light):self.light = lightdef execute(self):self.light.turn_off()# 接收者:电灯
class Light:def turn_on(self):print("灯打开了")def turn_off(self):print("灯关闭了")# 调用者:遥控器
class RemoteControl:def __init__(self):self.command = Nonedef set_command(self, command):self.command = commanddef press_button(self):if self.command:self.command.execute()# 客户端代码
def main():# 创建电灯对象light = Light()# 创建具体命令对象并将其绑定到接收者turn_on_command = TurnOnCommand(light)turn_off_command = TurnOffCommand(light)# 创建调用者对象并设置命令remote_control = RemoteControl()remote_control.set_command(turn_on_command)# 模拟按下按钮remote_control.press_button()# 设置另一个命令并再次按下按钮remote_control.set_command(turn_off_command)remote_control.press_button()if __name__ == "__main__":main()
- 输出结果
灯打开了
灯关闭了
模板方法模式
模板方法模式(Template Method Pattern)是一种行为设计模式,它定义了一个操作中的算法框架,将某些步骤延迟到子类中实现。这样,可以在不改变算法结构的情况下,重新定义算法中的某些步骤,从而实现代码重用和灵活性的增加。
模板方法模式的核心思想是定义一个抽象类,其中包含一个模板方法,该方法定义了算法的骨架,包括一系列的步骤,而这些步骤可以是具体实现或者是抽象方法。具体的子类可以通过实现这些抽象方法来提供算法中的具体步骤,从而定制化算法的行为。
-
抽象类(Abstract Class):定义了一个模板方法,其中包含算法的骨架和一系列的步骤,这些步骤可以是具体的实现或者是抽象方法,由子类来实现。
-
具体类(Concrete Class):继承自抽象类,并实现了抽象方法,提供了算法中的具体步骤的实现。
场景
-
框架设计:在框架设计中,通常会定义一个抽象类作为框架的核心,其中包含了一些公共的方法和模板方法,而具体的子类则通过实现模板方法来定制化框架的行为。这样可以保持框架的一致性和稳定性,同时又能够灵活地定制化框架的行为。
-
算法设计:在算法设计中,通常会定义一个抽象类作为算法的模板,其中包含了算法的骨架和一些公共的步骤,而具体的子类则通过实现抽象方法来提供算法中的具体步骤。这样可以保持算法的一致性和可扩展性,同时又能够灵活地定制化算法的行为。
-
代码生成工具:在代码生成工具中,通常会定义一个抽象类作为代码生成器的模板,其中包含了一些公共的方法和模板方法,而具体的子类则通过实现模板方法来生成不同语言或者不同框架的代码。这样可以实现代码的自动生成,并且保持代码的一致性和可扩展性。
-
流程控制:在流程控制中,通常会定义一个抽象类作为流程的模板,其中包含了流程的骨架和一些公共的步骤,而具体的子类则通过实现抽象方法来提供流程中的具体步骤。这样可以保持流程的一致性和可扩展性,同时又能够灵活地定制化流程的行为。
示例
from abc import ABC, abstractmethod# 抽象类:饮料
class Beverage(ABC):# 模板方法,定义了饮料的制作流程def prepare_beverage(self):self.boil_water()self.brew()self.pour_in_cup()self.add_condiments()# 具体步骤:煮水def boil_water(self):print("煮水")# 具体步骤:冲泡@abstractmethoddef brew(self):pass# 具体步骤:倒入杯中def pour_in_cup(self):print("倒入杯中")# 具体步骤:加入调料@abstractmethoddef add_condiments(self):pass# 具体类:咖啡
class Coffee(Beverage):# 实现冲泡方法def brew(self):print("用滤网滴取咖啡")# 实现加入调料方法def add_condiments(self):print("加入糖和牛奶")# 具体类:茶
class Tea(Beverage):# 实现冲泡方法def brew(self):print("泡茶")# 实现加入调料方法def add_condiments(self):print("加入柠檬")# 客户端代码
def main():print("制作咖啡:")coffee = Coffee()coffee.prepare_beverage()print("\n制作茶:")tea = Tea()tea.prepare_beverage()if __name__ == "__main__":main()
- 输出结果
制作咖啡:
煮水
用滤网滴取咖啡
倒入杯中
加入糖和牛奶制作茶:
煮水
泡茶
倒入杯中
加入柠檬
模板方法模式
模板方法模式(Template Method Pattern)是一种行为设计模式,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
在模板方法模式中,通常会有一个抽象类,该抽象类包含一个模板方法,模板方法定义了算法的骨架,包括一系列的步骤。其中一些步骤可能是具体的实现,而另一些步骤则可以是抽象的,由子类来实现。子类通过扩展或重写这些抽象方法来提供算法中的具体步骤,从而定制化算法的行为。
-
抽象类(Abstract Class):定义了一个模板方法,该方法包含算法的骨架和一系列的步骤,其中一些步骤可以是具体的实现,而另一些步骤则可以是抽象的,由子类来实现。
-
具体类(Concrete Class):继承自抽象类,并实现了抽象方法,提供了算法中的具体步骤的实现。
场景
-
定义算法框架:当需要定义一个算法的骨架,并且其中一些步骤可以具体实现,而另一些步骤需要延迟到子类中实现时,可以使用模板方法模式。这样可以确保算法的一致性和稳定性,同时又能够灵活地定制化算法的行为。
-
代码重用:当有多个类中存在类似的算法,并且这些算法的结构类似但具体步骤有所不同时,可以将公共部分抽象成模板方法,避免重复代码的产生,提高代码的重用性。
-
框架设计:在框架设计中,通常会定义一个抽象类作为框架的核心,其中包含了一些公共的方法和模板方法,而具体的子类则通过实现模板方法来定制化框架的行为。这样可以保持框架的一致性和稳定性,同时又能够灵活地定制化框架的行为。
-
流程控制:当有一系列步骤需要按照一定的顺序执行,并且其中某些步骤需要定制化时,可以使用模板方法模式。这样可以保持流程的一致性和稳定性,同时又能够灵活地定制化流程的行为。
示例
from abc import ABC, abstractmethod# 抽象类:制作食物
class Food(ABC):# 模板方法,定义了食物的制作流程def prepare_food(self):self.prepare_ingredients()self.cook()self.serve()# 具体步骤:准备食材def prepare_ingredients(self):print("准备食材")# 具体步骤:烹饪@abstractmethoddef cook(self):pass# 具体步骤:上菜def serve(self):print("上菜")# 具体类:炒菜
class StirFry(Food):# 实现烹饪方法def cook(self):print("炒菜")# 具体类:煮汤
class BoilSoup(Food):# 实现烹饪方法def cook(self):print("煮汤")# 客户端代码
def main():print("制作炒菜:")stir_fry = StirFry()stir_fry.prepare_food()print("\n制作煮汤:")boil_soup = BoilSoup()boil_soup.prepare_food()if __name__ == "__main__":main()
- 输出结果
制作炒菜:
准备食材
炒菜
上菜制作煮汤:
准备食材
煮汤
上菜
事件驱动模式
事件驱动模式(Event-driven architecture)是一种软件设计范式,其中系统的行为是由事件的发生和相应的处理来驱动的。在事件驱动模式中,系统中的组件通过发布和订阅事件的方式进行通信,当特定的事件发生时,相关的处理器会被调用来处理该事件。
-
事件(Event):系统中的行为或状态变化。事件可以是内部的状态变化,也可以是外部的触发动作,比如用户输入、网络消息等。
-
事件源(Event Source):产生事件的组件或对象。事件源可以是用户界面、传感器、网络等。
-
事件处理器(Event Handler):用于处理特定类型事件的组件或函数。当事件发生时,相应的事件处理器会被调用来处理事件。
-
事件监听器(Event Listener):监听并处理特定类型事件的组件或函数。事件监听器通常会订阅感兴趣的事件,当事件发生时,会调用相应的事件处理器来处理事件。
场景
-
图形用户界面(GUI):图形界面中的用户操作(如鼠标点击、键盘输入)都可以看作是事件,GUI 库通常会提供事件监听器和处理器,用于处理这些事件,从而实现交互式界面。
-
网络编程:在网络编程中,事件驱动模式常用于处理网络消息和连接状态变化。例如,在异步网络框架中,可以注册事件监听器来处理接收到的网络消息和连接的建立或关闭事件。
-
服务器端开发:服务器端开发中经常需要处理大量的并发请求,事件驱动模式可以帮助实现高效的并发处理。例如,在 Web 服务器中,可以使用事件驱动模式来处理 HTTP 请求和响应。
-
游戏开发:游戏开发中的用户操作、碰撞检测、动画效果等都可以看作是事件,游戏引擎通常会提供事件系统来处理这些事件,从而实现游戏逻辑。
-
消息队列系统:消息队列系统通常使用事件驱动模式来处理消息的生产和消费。消息生产者将消息发送到队列中,消息消费者注册事件监听器来处理队列中的消息。
-
分布式系统:在分布式系统中,节点之间的通信和数据传输都可以看作是事件,事件驱动模式可以帮助实现分布式系统中的消息传递和事件处理。
示例
from abc import ABC, abstractmethod# 抽象事件源
class EventSource(ABC):def __init__(self):self.listeners = []def add_listener(self, listener):self.listeners.append(listener)def remove_listener(self, listener):self.listeners.remove(listener)@abstractmethoddef notify_listeners(self, event):pass# 具体事件源:按钮
class Button(EventSource):def click(self):print("按钮被点击了")self.notify_listeners("click")def notify_listeners(self, event):for listener in self.listeners:listener.handle_event(event)# 抽象事件监听器
class EventListener(ABC):@abstractmethoddef handle_event(self, event):pass# 具体事件监听器:日志记录器
class Logger(EventListener):def handle_event(self, event):print("日志记录器记录事件:{}".format(event))# 具体事件监听器:邮件通知器
class EmailNotifier(EventListener):def handle_event(self, event):print("邮件通知器发送邮件:事件{}".format(event))# 客户端代码
def main():button = Button()logger = Logger()email_notifier = EmailNotifier()button.add_listener(logger)button.add_listener(email_notifier)# 模拟按钮点击事件button.click()if __name__ == "__main__":main()
- 输出结果
按钮被点击了
日志记录器记录事件:click
邮件通知器发送邮件:事件click
责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。在责任链模式中,请求沿着一条链传递,直到有一个对象处理请求为止。
-
Handler(处理者):定义了一个处理请求的接口,并维护了一个指向下一个处理者的引用。处理者通常包含一个处理请求的方法,用于处理请求或将请求传递给下一个处理者。
-
ConcreteHandler(具体处理者):实现了处理请求的具体逻辑,并在必要时将请求传递给下一个处理者。每个具体处理者都负责处理一种或多种类型的请求。
-
Client(客户端):创建一个责任链,并向链中的第一个处理者发送请求。客户端通常不知道链中的具体处理者是谁,只需要将请求发送给责任链的第一个处理者即可。
场景
-
请求处理链:当有多个对象都有机会处理同一个请求时,可以使用责任链模式。例如,一个网络服务器可以有多个中间件组成的处理链来处理请求,每个中间件负责处理特定类型的请求或执行特定的处理逻辑。
-
日志记录:在日志记录系统中,可以使用责任链模式来实现不同级别日志的记录。例如,一个日志记录器链可以包含多个具体日志记录器,每个日志记录器负责记录特定级别的日志。
-
权限管理:在权限管理系统中,可以使用责任链模式来实现权限检查的处理链。例如,一个权限检查器链可以包含多个具体权限检查器,每个权限检查器负责检查特定权限是否被授权。
-
事件处理:在事件驱动系统中,可以使用责任链模式来处理事件的传递和处理。例如,一个事件处理器链可以包含多个具体事件处理器,每个事件处理器负责处理特定类型的事件。
-
异常处理:在异常处理系统中,可以使用责任链模式来处理异常的传递和处理。例如,一个异常处理器链可以包含多个具体异常处理器,每个异常处理器负责处理特定类型的异常。
示例
from abc import ABC, abstractmethod# 抽象处理者
class Handler(ABC):def __init__(self, successor=None):self.successor = successor@abstractmethoddef handle_request(self, request):pass# 具体处理者A
class ConcreteHandlerA(Handler):def handle_request(self, request):if request == "A":print("ConcreteHandlerA处理请求{}".format(request))elif self.successor:self.successor.handle_request(request)# 具体处理者B
class ConcreteHandlerB(Handler):def handle_request(self, request):if request == "B":print("ConcreteHandlerB处理请求{}".format(request))elif self.successor:self.successor.handle_request(request)# 具体处理者C
class ConcreteHandlerC(Handler):def handle_request(self, request):if request == "C":print("ConcreteHandlerC处理请求{}".format(request))elif self.successor:self.successor.handle_request(request)# 客户端代码
def main():handler_a = ConcreteHandlerA()handler_b = ConcreteHandlerB()handler_c = ConcreteHandlerC()handler_a.successor = handler_bhandler_b.successor = handler_c# 构建处理链,传递请求handler_a.handle_request("A")handler_a.handle_request("B")handler_a.handle_request("C")handler_a.handle_request("D")if __name__ == "__main__":main()
- 输出结果
ConcreteHandlerA处理请求A
ConcreteHandlerB处理请求B
ConcreteHandlerC处理请求C
中介者模式
中介者模式(Mediator Pattern)是一种行为设计模式,它通过引入一个中介者对象来封装一系列对象之间的交互。中介者模式可以降低对象之间的直接耦合,使得对象之间的通信更加松散和灵活。
在中介者模式中,通常会有一个中介者对象,该对象负责协调和管理其他对象之间的交互。当一个对象需要与其他对象进行通信时,它不会直接与其他对象进行交互,而是通过中介者对象来进行间接通信。这样一来,对象之间的耦合度就会降低,同时也更容易扩展和维护系统。
-
中介者(Mediator):定义了一个接口用于与其他对象进行通信,并维护了一个对各个对象的引用。中介者对象通常负责协调和管理对象之间的交互。
-
具体中介者(Concrete Mediator):实现了中介者接口,并负责协调和管理具体的对象之间的交互。具体中介者通常包含了对各个对象的引用,以便于进行通信和协调。
-
同事对象(Colleague):定义了一个接口用于与中介者进行通信,并维护了一个对中介者的引用。同事对象通常会将自己的状态和行为委托给中介者对象来处理。
-
具体同事对象(Concrete Colleague):实现了同事对象接口,并负责实现自己的状态和行为。具体同事对象通常会将自己的状态和行为委托给中介者对象来处理。
场景
-
图形用户界面(GUI):在图形用户界面中,各种组件之间的交互比较复杂,例如按钮、文本框、下拉框等组件之间的交互。中介者模式可以将这些组件之间的交互逻辑集中到一个中介者对象中,从而降低了组件之间的耦合度。
-
聊天室:在聊天室中,用户之间可以发送消息进行交流,而用户之间的消息需要通过服务器进行中转。中介者模式可以将聊天室中用户之间的消息交流集中到一个中介者对象中,从而简化了用户之间的交流过程。
-
交通管理系统:在交通管理系统中,各种交通工具之间需要进行交通管制,例如汽车、公交车、地铁等交通工具之间的交通管制。中介者模式可以将这些交通工具之间的交通管制集中到一个中介者对象中,从而降低了交通工具之间的耦合度。
-
游戏开发:在游戏开发中,各种游戏对象之间需要进行交互,例如玩家、敌人、道具等游戏对象之间的交互。中介者模式可以将这些游戏对象之间的交互集中到一个中介者对象中,从而简化了游戏对象之间的交互逻辑。
-
分布式系统:在分布式系统中,各个节点之间需要进行消息传递和数据交换。中介者模式可以将这些节点之间的消息传递和数据交换集中到一个中介者对象中,从而简化了节点之间的通信逻辑。
示例
from abc import ABC, abstractmethod# 抽象中介者
class Mediator(ABC):@abstractmethoddef send(self, message, colleague):pass# 具体中介者
class ConcreteMediator(Mediator):def __init__(self):self.colleague1 = Noneself.colleague2 = Nonedef set_colleague1(self, colleague):self.colleague1 = colleaguedef set_colleague2(self, colleague):self.colleague2 = colleaguedef send(self, message, colleague):if colleague == self.colleague1:self.colleague2.receive(message)else:self.colleague1.receive(message)# 抽象同事类
class Colleague(ABC):def __init__(self, mediator):self.mediator = mediator@abstractmethoddef send(self, message):pass@abstractmethoddef receive(self, message):pass# 具体同事类1
class ConcreteColleague1(Colleague):def send(self, message):print("同事1发送消息: {}".format(message))self.mediator.send(message, self)def receive(self, message):print("同事1接收消息: {}".format(message))# 具体同事类2
class ConcreteColleague2(Colleague):def send(self, message):print("同事2发送消息: {}".format(message))self.mediator.send(message, self)def receive(self, message):print("同事2接收消息: {}".format(message))# 客户端代码
def main():mediator = ConcreteMediator()colleague1 = ConcreteColleague1(mediator)colleague2 = ConcreteColleague2(mediator)mediator.set_colleague1(colleague1)mediator.set_colleague2(colleague2)colleague1.send("你好,同事2,我是同事1。")colleague2.send("你好,同事1,我是同事2。")if __name__ == "__main__":main()
- 输出结果
同事1发送消息: 你好,同事2,我是同事1。
同事2接收消息: 你好,同事2,我是同事1。
同事2发送消息: 你好,同事1,我是同事2。
同事1接收消息: 你好,同事1,我是同事2。
状态模式
状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态发生改变时改变其行为。状态模式通过将对象的状态封装成独立的状态类,并将对象的行为委托给当前状态类来实现状态的切换和行为的变化。
在状态模式中,通常会有一个环境类(Context),该类维护了一个当前状态对象,并提供了一个接口来允许客户端代码改变状态。每个具体状态类(Concrete State)表示了环境对象的一种具体状态,并实现了在该状态下的行为。环境类在接收到状态改变的请求时,会将请求委托给当前状态对象来处理。
状态模式的核心思想是将对象的状态和行为分离,使得状态可以独立于对象而变化。这样一来,当对象的状态发生改变时,只需要改变当前状态对象,而不需要修改对象的行为或者其他状态对象。这样就提高了系统的灵活性和可扩展性,并且遵循了开闭原则。
-
环境类(Context):维护一个当前状态对象,并提供了一个接口来允许客户端代码改变状态。
-
抽象状态类(State):定义了一个接口,用于封装环境对象的一种具体状态,并声明了在该状态下的各种行为。
-
具体状态类(Concrete State):实现了抽象状态类定义的接口,并实现了在该状态下的具体行为。
场景
-
对象具有多种状态:当对象具有多种状态,并且状态之间的转换会导致对象行为发生改变时,可以考虑使用状态模式。例如,订单在待支付、已支付、已发货、已完成等多种状态之间切换,每种状态对应着不同的行为。
-
条件语句复杂:当对象的行为由多个条件语句组成,且条件之间存在交互和重叠时,可以考虑使用状态模式来简化条件语句。状态模式将每个状态封装成一个独立的对象,使得对象的行为在不同状态下的处理变得清晰和简单。
-
状态转换频繁:当对象的状态转换频繁,并且状态之间的转换规则较为复杂时,可以考虑使用状态模式。状态模式将状态转换的逻辑封装到状态类中,使得状态之间的转换更加灵活和易于维护。
-
行为和状态之间的依赖关系:当对象的行为和状态之间存在一对多的依赖关系时,可以考虑使用状态模式。状态模式可以将行为和状态解耦,使得对象的行为更加灵活和可扩展。
示例
from abc import ABC, abstractmethod# 抽象状态类
class State(ABC):@abstractmethoddef handle(self):pass# 具体状态类:开机状态
class PowerOnState(State):def handle(self):print("已开机,欢迎使用!")# 具体状态类:关机状态
class PowerOffState(State):def handle(self):print("已关机,再见!")# 环境类
class Computer:def __init__(self):self.state = Nonedef set_state(self, state):self.state = statedef power_on(self):self.set_state(PowerOnState())self.state.handle()def power_off(self):self.set_state(PowerOffState())self.state.handle()# 客户端代码
def main():computer = Computer()computer.power_on()computer.power_off()if __name__ == "__main__":main()
- 输出结果
已开机,欢迎使用!
已关机,再见!