类和对象如何交互,及划分责任和算法。
共分为以下几种:解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模板方法模式。
解释器模式
责任链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。讲这些对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止。
角色
- 抽象处理者(Handler)
- 具体处理者(ConcreteHandler)
- 客户端(Client)
适用场景
- 有多个对象可以处理一个请求,哪个对象处理由运行时决定
- 在不明确接受者的情况下,向多个对象中的一个提交一个请求
优点
- 降低耦合度:一个对象无需知道是其他哪一个对象处理的请求
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| from abc import ABCMeta, abstractmethod
class Handler(metaclass=ABCMeta): @abstractmethod def handler_leave(self, days): pass
class GeneralManager(Handler):
def handler_leave(self, days): if days <= 10: print(f"总经理准假{days}天") else: print("请假天数过多,没有人可以批准")
class BranchManager(Handler): def __init__(self): self.next = GeneralManager()
def handler_leave(self, days): if days <= 5: print(f"部门经理准假{days}天") else: print("请假天数过多,部门经理没有批准权限") self.next.handler_leave(days)
class ProductManager(Handler):
def __init__(self): self.next = BranchManager()
def handler_leave(self, days): if days <= 3: print(f"产品经理准假{days}天") else: print("请假天数过多,产品经理没有批准权限") self.next.handler_leave(days)
day = 9 ProductManager().handler_leave(day)
|
命令模式
迭代器模式
中介者模式
备忘录模式
观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,观察者模式又称发布-订阅模式
角色
- 抽象主题(Subject)
- 具体主题(ConcreteSubject)-发布者
- 抽象观察者(Observer)
- 具体观察者(ConcreteObserver)-订阅者/观察者
适用场景
- 当一个抽象模型有两方面,其中一个方面依赖于另一个方面。将这两者封装在独立对象中以使它们可以各自独立的改变和复用
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变时
- 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之,你不希望这些对象是紧密耦合的时候
优点
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| from abc import ABCMeta, abstractmethod
class Observer(metaclass=ABCMeta): @abstractmethod def update(self, notice): pass
class Publisher(metaclass=ABCMeta): def __init__(self): self.observers = []
def attach(self, observer_obj): self.observers.append(observer_obj)
def detach(self, observer_obj): self.observers.remove(observer_obj)
def notify(self): [observer_obj.update(self) for observer_obj in self.observers]
class CompanyPublisher(Publisher): def __init__(self, info=None): super().__init__() self.__info = info
@property def info(self): return self.__info
@info.setter def info(self, info): self.__info = info self.notify()
class StaffObserver(Observer): def __init__(self): self.info = None
def update(self, notice): self.info = notice.info
staff1 = StaffObserver()
staff2 = StaffObserver()
c = CompanyPublisher("我是公司公告")
c.attach(staff1)
c.attach(staff2)
c.info = "新人守则,请大家仔细阅读" print(staff1.info) print(staff2.info)
print("-------------------------------------")
c.detach(staff2)
c.info = "新年快乐,公司公告" print(staff1.info) print(staff2.info)
|
运行结果
1 2 3 4 5
| 新人守则,请大家仔细阅读 新人守则,请大家仔细阅读 ------------------------------------- 新年快乐,公司公告 新人守则,请大家仔细阅读
|
状态模式
策略模式
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
角色
- 抽象策略(Strategy)
- 具体策略(ConcreteStrategy)
- 上下文(Context)
优点
- 定义了一系列可重用的算法和行为
- 消除了一些条件语句
- 可以提供相同行为的不同实现
缺点
客户必须了解不同的策略
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| from abc import ABCMeta, abstractmethod
class Strategy(metaclass=ABCMeta): @abstractmethod def execute(self, data): pass
class FirstStrategy(Strategy): def execute(self, data): print(f"我是策略一【{data}】")
class SecondStrategy(Strategy): def execute(self, data): print(f"我是策略二【{data}】")
class Context: def __init__(self, strategy, data): self.strategy = strategy self.data = data
def change_strategy(self, strategy): self.strategy = strategy
def do_strategy(self): self.strategy.execute(self.data)
first = FirstStrategy()
second = SecondStrategy()
data = "data……"
c = Context(first, data)
c.do_strategy()
c.change_strategy(second)
c.do_strategy()
|
执行结果
1 2
| 我是策略一【data……】 我是策略二【data……】
|
访问者模式
模板方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟(具体实现)到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
角色
- 抽象类(AbstractClass):定义抽象的原子操作(狗子操作);实现一个模板方法作为算法的骨架。
- 具体类(ConcreteClass):实现(具体代码)原子操作
适用场景
- 一次性实现一个算法的不变的部分
- 各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复
- 控制子类扩展
示例
代码运行中已使用ctrl+c强制结束,所以窗口只绘制了4次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| import random import time from abc import ABCMeta, abstractmethod
class Window(metaclass=ABCMeta): @abstractmethod def start(self): """窗口开始后要执行的逻辑代码""" pass
@abstractmethod def repaint(self): """窗口变化绘制的逻辑代码""" pass
@abstractmethod def close(self): """窗口关闭要执行的逻辑代码""" pass
def run(self): """窗口正常运行流程""" self.start() while True: try: self.repaint() time.sleep(random.randint(1, 3)) except KeyboardInterrupt: break self.close()
class MyWindow(Window): def __init__(self, data): self.data = data
def start(self): print("窗口开始运行代码逻辑……")
def repaint(self): print(f"窗口绘制内容为:{self.data}-{random.randint(10000000, 999999999)}")
def close(self): print("窗口关闭运行代码逻辑")
w = MyWindow("Windows内容体") w.run()
|
运行结果:
1 2 3 4 5 6
| 窗口开始运行代码逻辑…… 窗口绘制内容为:Windows内容体-167964939 窗口绘制内容为:Windows内容体-23453276 窗口绘制内容为:Windows内容体-624587516 窗口绘制内容为:Windows内容体-79282804 窗口关闭运行代码逻辑
|