Python设计模式——行为型模式

责任链模式

  • 内容:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
  • 角色
    • 抽象处理者(Handler)
    • 具体处理者(ConcreteHandler)
    • 客户端(Client)
from abc import ABCMeta, abstractmethod


class Handler(metaclass=ABCMeta):
    @abstractmethod
    def handle_leave(self, day):
        pass


class GeneralManager(Handler):
    def handle_leave(self, day):
        if day < 10:
            print(f"总经理准假{day}天")
        else:
            print("你还是辞职吧")


class DepartmentManager(Handler):
    def __init__(self):
        self.next = GeneralManager()

    def handle_leave(self, day):
        if day < 7:
            print(f"部门经理准假{day}天")
        else:
            print("部门经理职权不够,交给总经理处理")
            self.next.handle_leave(day)


class ProjectDirector(Handler):
    def __init__(self):
        self.next = DepartmentManager()

    def handle_leave(self, day):
        if day < 3:
            print(f"项目主管准假{day}天")
        else:
            print("项目主管职权不够,交给部门经理处理")
            self.next.handle_leave(day)


# 客户端
day = 4
h = ProjectDirector()
h.handle_leave(day)
项目主管职权不够,交给部门经理处理
部门经理准假4天
  • 适用场景:
    • 有多个对象可以处理一个请求,哪个对象处理由运行时决定
    • 在不明确接收者的情况下,向多个对象中的一个提交一个请求
  • 优点:
    • 降低耦合度:一个对象无需知道是其他哪一个对象处理其请求

观察者模式

  • 内容:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。观察者模式又称“发布-订阅”模式
  • 角色
    • 抽象主题(Subject)
    • 具体主题(ConcreteSubject)————发布者
    • 抽象观察者(Observer)
    • 具体观察者(ConcreteObserver)————订阅者
from abc import ABCMeta, abstractmethod


# 订阅者
class Observer(metaclass=ABCMeta):
    @abstractmethod
    def update(self, notice): # notice是一个Notice类的实例
        pass


# 具体订阅者
class Staff(Observer):
    def __init__(self, name):
        self.name = name
        self.company_info = None

    def update(self, notice):
        self.company_info = notice.company_info


# 抽象发布者
class Notice:  
    def __init__(self):
        self.observers = []

    def attach(self, observer):
        self.observers.append(observer)

    def detach(self, observer):
        if observer in self.observers:
            self.observers.remove(observer)

    # 通知所有订阅者
    def notify(self):
        for obs in self.observers:
            obs.update(self)


# 具体发布者
class StaffNotice(Notice):  
    def __init__(self, company_info=None):
        super().__init__()
        self.__company_info = company_info

    # 访问或更改私有属性
    @property
    def company_info(self):
        return self.__company_info
    
    @company_info.setter
    def company_info(self, new_info):
        self.__company_info = new_info
        self.notify()  # 关键步骤:更新消息后自动通知所有订阅者


# obj = StaffNotice("明天放假")
# print(obj.company_info)
# obj.company_info = "后天放假"
# print(obj.company_info)

notice = StaffNotice('初始信息')
obj1 = Staff('张三')
obj2 = Staff('李四')

notice.attach(obj1)
notice.attach(obj2)

notice.company_info = '明天放假'
print(obj1.company_info)
明天放假
  • 适用场景:
    • 当一个抽象模型有两方面,其中一个方面依赖于另一个方面。将这两者封装在独立对象中以使它们可以各自独立地改变和复用。
    • 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
    • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
  • 优点:
    • 目标和观察者之间的抽象耦合最小
    • 支持广播通信

策略模式

  • 内容:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
  • 角色:
    • 抽象策略(Strategy)
    • 具体策略(ConcreteStrategy)
    • 多上下文(Context)
from abc import ABCMeta, abstractmethod


class Strategy(metaclass=ABCMeta):
    @abstractmethod
    def execute(self, data):
        pass


class FastStrategy(Strategy):
    def execute(self, data):
        print(f"采用快速策略处理{data}")


class SlowStrategy(Strategy):
    def execute(self, data):
        print(f"采用慢速策略处理{data}")


class Context:
    def __init__(self, strategy, data):
        self.data = data
        self.strategy = strategy

    def set_strategy(self, strategy):
        self.strategy = strategy

    def do_strategy(self):
        self.strategy.execute(self.data)


# 客户端
data = 'data...'
s1 = FastStrategy()
context = Context(s1, data)
context.do_strategy()

s2 = SlowStrategy()
context.set_strategy(s2)
context.do_strategy()
采用快速策略处理data...
采用慢速策略处理data...
  • 优点:
    • 定义了一系列可重用的算法和行为
    • 消除了一些条件语句
    • 可以提供相同行为的不同实现
  • 缺点:
    • 多客户必须了解不同的策略

模板方法模式

  • 内容:定义一个操作中的算法的骨架,而将一些步聚延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
  • 角色
    • 抽象类(AbstractClass):定义抽象的原子操作(钩子操作);实现一个模板方法作为算法的骨架。
    • 具体类(ConcreteClass):实现原子操作
from abc import ABCMeta, abstractmethod
from time import sleep


class Window(metaclass=ABCMeta):
    @abstractmethod
    def start(self):
        pass

    @abstractmethod
    def repaint(self):
        pass

    @abstractmethod
    def stop(self):  # 原子操作/钩子操作
        pass

    def run(self):  # 模板方法
        self.start()
        while True:
            try:
                self.repaint()
                sleep(1)
            except KeyboardInterrupt:
                print('终止')
                break
        self.stop()


class MyWindow(Window):
    def __init__(self, msg):
        self.msg = msg

    def start(self):
        print('窗口开始运行')

    def repaint(self):
        print(self.msg)

    def stop(self):
        print('窗口停止运行')


MyWindow('Hello, World!').run()
窗口开始运行
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Hello, World!
终止
窗口停止运行
  • 适用场景:
    • 一次性实现一个算法的不变的部分
    • 各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复
    • 控制子类扩展
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值