设计模式_行为型模式
目录
行为型模式:
解释器模式
略。
责任链模式
一、内容
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求
直到有一个对象处理它为止
二、角色
- 抽象处理者
- 具体处理者
- 客户端
例:请假部门批准:项目主管----》部门经理----》总经理
三、优点
- 降低耦合度:一个对象无需知道是其他哪一个对象处理其请求
四、缺点
- 请求不保证被接收:链的末端没有处理或者链配置错误
五、适用场景
- 有多个对象可以处理一个请求,哪个对象处理由时间运行时决定
- 在不明确接受者的情况下,向多个对象中的一个提交一个请求
六 、示例代码
from abc import ABCMeta, abstractmethod # class Handler(metaclass=ABCMeta): @abstractmethod def handle_leave(self, day): pass class GeneralManagerHandler(Handler): def handle_leave(self, day): if day < 10: print("总经理批准%d天假"%day) else: print("呵呵") class DepartmentManagerHandler(Handler): def __init__(self): self.successor = GeneralManagerHandler() #责任链的后面的一个人 def handle_leave(self, day): if day < 7: print("部门经理批准%d天假"%day) else: print("部门经理无权准假") self.successor.handle_leave(day) class ProjectDirectorHandler(Handler): def __init__(self): self.successor = DepartmentManagerHandler() def handle_leave(self, day): if day < 3: print("项目主管批准%d天假") else: print("项目主管无权准假") self.successor.handle_leave(day) day = 4 h = ProjectDirectorHandler() h.handle_leave(day)
#--高级例子--模仿js事件处理 # JavaScript中假如有三个嵌套的div,每个div绑定一个事件,就像冒泡一样,先找里面的, # 如果里面有就是里面的事件,如果里面没有就找上一层的。以此类推 from abc import ABCMeta, abstractmethod class Handler(metaclass=ABCMeta): @abstractmethod def add_event(self, func): pass @abstractmethod def handle(self): pass class BodyHandler(Handler): def __init__(self): self.func = None def add_event(self, func): self.func = func def handle(self): if self.func: return self.func() else: print("已到最后一级,无法处理") class ElementHandler(Handler): def __init__(self, successor): self.func = None self.successor = successor def add_event(self, func): self.func = func def handle(self): if self.func: return self.func() else: return self.successor.handle() # 客户端 # <body><div><a> body = {'type': 'body', 'name': 'body', 'children': [], 'father': None} div = {'type': 'div', 'name': 'div', 'children': [], 'father': body} a = {'type': 'a', 'name': 'a', 'children': [], 'father': div} body['children'].append(div) div['children'].append(a) body['event_handler'] = BodyHandler() div['event_handler'] = ElementHandler(div['father']['event_handler']) a['event_handler'] = ElementHandler(a['father']['event_handler']) def attach_event(element, func): element['event_handler'].add_event(func) #test def func_div(): print("这是给div的函数") def func_a(): print("这是给a的函数") def func_body(): print("这是给body的函数") # attach_event(div, func_div) attach_event(a, func_a) # attach_event(body, func_body) a['event_handler'].handle()
命令模式
略。
迭代器模式
一、内容
提供一种方法顺序访问一个聚合函数一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示
二、实现方法
迭代器内部实现:__iter__、__next__方法
三、代码实现
class LinkList: """链表 头结点保存链表的长度""" class Node: def __init__(self, item=None): self.item = item self.next = None class LinkListIterator: def __init__(self, node): self.node = node def __next__(self): if self.node: cur_node = self.node self.node = cur_node.next return cur_node.item else: raise StopIteration def __iter__(self): return self def __init__(self, iterable=None): self.head = LinkList.Node(0) self.tail = self.head self.extend(iterable) def append(self, obj): s = LinkList.Node(obj) self.tail.next = s self.tail = s def extend(self, iterable): for obj in iterable: self.append(obj) self.head.item += len(iterable) def __iter__(self): return self.LinkListIterator(self.head.next) def __len__(self): return self.head.item def __str__(self): return "<<"+", ".join(map(str, self))+">>" li = [i for i in range(100)] print(li) lk = LinkList(li) # for i in lk: # print(i) print(lk) # print(len(lk))
中介者模式
略。
备忘录模式
略。
观察者模式
一、内容
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都得到通知并被自动更新。
观察者模式又称‘发布-订阅’模式
二、角色
- 抽象主题(Subject)
- 具体主题(ConcreteSubject)——发布者
- 抽象观察者(Observer)
- 具体观察者(ConcreteObserver)——订阅者
三、优点
- 目标和观察者之间的抽象耦合最小
- 支持广播通信
四、缺点
- 多个观察者之间互不知道对方存在,因此一个观察者对主题的修改可能造成错误的更新。
五、适用场景
- 当一个抽象模型有两方面,其中一方面依赖于另一方面。将这两者封装在独立对象中以使它们可以独立地改变和复用。
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
- 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之,你不希望这些对象是紧密耦合的
六、代码示例
from abc import ABCMeta, abstractmethod class Observer(metaclass=ABCMeta): @abstractmethod def update(self, notice): pass class Notice: def __init__(self): self.observers = [] # 记录该主体的观察者(订阅者) def attach(self, obs): self.observers.append(obs) def detach(self, obs): obs.company_info = None self.observers.remove(obs) def notify(self): for obj in self.observers: obj.update(self) class ManagerNotice(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, info): self.__company_info = info self.notify() class Manager(Observer): def __init__(self): self.company_info = None def update(self, noti): self.company_info = noti.company_info notice = ManagerNotice() alex = Manager() wusir = Manager() # print(alex.company_info) # print(wusir.company_info) notice.attach(alex) notice.attach(wusir) # notice.company_info="公司运行良好" # print(alex.company_info) print(wusir.company_info) # notice.detach(wusir) # notice.company_info="公司要破产了" print(alex.company_info) print(wusir.company_info)
状态模式
略。
策略模式
一、内容
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
二、角色
- 抽象策略(Strategy)
- 具体策略(ConcreteStrategy)
- 上下文(Context)
三、优点
- 定义了一系列可重用的算法和行为
- 消除了一些条件语句
- 可以提供相同行为的不同实现
四、缺点
- 客户必须了解不同的策略
- 策略与上下文之间的通信开销
- 增加了对象的数目
五、适用场景
- 许多相关的类仅仅是行为有异
- 需要使用一个算法的不同变体
- 算法使用了客户端无需知道的数据
一个类中的多种行为以多个条件语句的形式存在,可以将这些行为封装如不同的策略类中
六、示例代码
from abc import ABCMeta, abstractmethod import random class Sort(metaclass=ABCMeta): @abstractmethod def sort(self, data): pass class QuickSort(Sort): def quick_sort(self, data, left, right): if left < right: mid = self.partition(data, left, right) self.quick_sort(data, left, mid - 1) self.quick_sort(data, mid + 1, right) def partition(self, data, left, right): tmp = data[left] while left < right: while left < right and data[right] >= tmp: right -= 1 data[left] = data[right] while left < right and data[left] <= tmp: left += 1 data[right] = data[left] data[left] = tmp return left def sort(self, data): print("快速排序") return self.quick_sort(data, 0, len(data) - 1) class MergeSort(Sort): def merge(self, data, low, mid, high): i = low j = mid + 1 ltmp = [] while i <= mid and j <= high: if data[i] <= data[j]: ltmp.append(data[i]) i += 1 else: ltmp.append(data[j]) j += 1 while i <= mid: ltmp.append(data[i]) i += 1 while j <= high: ltmp.append(data[j]) j += 1 data[low:high + 1] = ltmp def merge_sort(self, data, low, high): if low < high: mid = (low + high) // 2 self.merge_sort(data, low, mid) self.merge_sort(data, mid + 1, high) self.merge(data, low, mid, high) def sort(self, data): print("归并排序") return self.merge_sort(data, 0, len(data) - 1) class Context: def __init__(self, data, strategy=None): self.data = data self.strategy = strategy def set_strategy(self, strategy): self.strategy = strategy def do_strategy(self): if self.strategy: self.strategy.sort(self.data) else: raise TypeError li = list(range(100000)) random.shuffle(li) context = Context(li, MergeSort()) context.do_strategy() #print(context.data) random.shuffle(context.data) context.set_strategy(QuickSort()) context.do_strategy()
访问者模式
略。
模板方法模式
一、内容
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
二、角色
- 抽象类:定义抽象的原子操作(钩子操作);实现一个模板方法的骨架
- 具体类:实现原子操作
三、适用场景
- 一次性实现一个算法的不变的部分
- 各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复
- 控制子类扩展
四、示例代码
from abc import ABCMeta, abstractmethod class IOHandler(metaclass=ABCMeta): @abstractmethod def open(self, name): pass @abstractmethod def deal(self, change): pass @abstractmethod def close(self): pass def process(self, name, change): '''模板,就相当于是一个空盒子,可以往里面添加自己需要的功能。让这个函数去执行''' self.open(name) self.deal(change) self.close() class FileHandler(IOHandler): def open(self, name): print('打开文件') def deal(self, change): print('操作文件') def close(self): print('关闭文件') obj = FileHandler() obj.process('abc.txt','')