python设计模式
文章目录
前言
设计模式分类:
创建型模式(5种):工厂方法模式、抽象工厂模式、创建者模式、(原型模式)、单例模式
结构型模式(7种):适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式
行为型模式(11种):解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模版方法模式
提示:以下是本篇文章正文内容,下面案例可供参考
一、创建型模式
二、结构型模式
控制类组成结构
1.适配器模式
- 内容:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
- 两种实现方式:
-1. 类适配器:使用多继承
-2. 对象适配器:使用组合
2.桥模式
- 内容:将一个事物的两个维度分离,使其都可以独立地变化。
from abc import ABCMeta, abstractmethod
class Shape(metaclass=ABCMeta):
def __init__(self, color):
self.color = color
@abstractmethod
def draw(self):
pass
class Color(metaclass=ABCMeta):
@abstractmethod
def paint(self, shape):
pass
class Rectangle(Shape):
name = "长方形"
def draw(self):
self.color.paint(self)
class Circle(Shape):
name = "圆形"
def draw(self):
self.color.paint(self)
class Red(Color):
def paint(self,shape):
print("红色的%s"%shape.name)
class Green(Color):
def paint(self,shape):
print("绿色的%s"%shape.name)
shape = Rectangle(Red())
shape.draw()
3.组合模式
- 内容:将对象组合成树形状以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
- 角色:
-1. 抽象组件
-2. 叶子组件
-3. 复合组件
-4. 客户端
from abc import ABCMeta, abstractmethod
# 抽象组件
class Graphic(metaclass=ABCMeta):
@abstractmethod
def draw(self):
pass
# 叶子组件
class Point(Graphic):
def __init__(self,x,y):
self.x = x
self.y = y
def __str__(self):
return "点(%s, %s)"%(self.x, self.y)
def draw(self):
print(str(self))
# 叶子组件
class Line(Graphic):
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
def __str__(self):
return "线段[%s, %s]" %(self.p1, self.p2)
def draw(self):
print(str(self))
# 复合组件
class Picture(Graphic):
def __init__(self, iterable):
self.children = []
for g in iterable:
self.add(g)
def add(self,graphic):
self.children.append(graphic)
def draw(self):
print("----复合图形----")
for g in self.children:
g.draw()
print("----复合图形----")
l = Line(Point(1,1),Point(2,2))
print(l)
l.draw()
p1 = Point(2,3)
l1 = Line(Point(3,4),Point(6,7))
l2 = Line(Point(1,5),Point(2,8))
pic1 = Picture([p1,l1,l2])
pic1.draw()
4. 外观模式
- 内容: 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口, 这个接口使得这一子系统更加容易使用.
- 角色:
-1. 外观
-2. 子系统类
5. 代理模式
- 内容: 为其他对象提供一种代理以控制对这个对象的访问.
- 应用场景:
-1. 远程代理: 为远程的对象提供代理
-2. 虚代理: 根据需要创建很大的对象
-3. 保护代理: 控制对原始对象的访问, 用于对象有不同访问权限时
三、行为型模式
1. 责任链模式
- 内容: 使多个对象都有机会处理请求, 从而避免请求的发送者和接受者之间的耦合关系. 将这些对象连城一条链, 并沿着这条链传递该请求, 直到有一个对象处理它为止.
- 角色:
-1. 抽象处理者(Handler)
-2. 具体处理者(ConcreteHandler)
-3. 客户端(Client)
from abc import ABCMeta, abstractmethod
class Handler(metaclass=ABCMeta):
@abstractmethod
def handle_level(self, day):
pass
class GeneralManager(Handler):
def handle_level(self, day):
if day < 10:
print("总理经准假%d天"%day)
else:
print("请假超过10天,你还是辞职吧")
class DepartmentManager(Handler):
def __init__(self):
self.next = GeneralManager()
def handle_level(self, day):
if day <=5:
print("部门经理准假%d天"%day)
else:
print("部门经理职权不足")
self.next.handle_level(day)
class ProjectDirector(Handler):
def __init__(self):
self.next = DepartmentManager()
def handle_level(self, day):
if day<=3:
print("项目主管准假%d天"%day)
else:
print("项目主管职权不足")
self.next.handle_level(day)
# 高层代码 client
day = 8
h = ProjectDirector()
h.handle_level(day)
2. 观察者模式(发布-订阅模式)
- 内容: 定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时, 所有依赖于它的对象都能得到通知并被自动更新. 观察者模式又称"发布-订阅"模式
- 角色:
-1. 抽象主题(Subject)
-2. 具体主题(ConcreteSubject) – 发布者
-3. 抽象观察者(Observer)
-4. 具体观察者(ConcreteObserver) – 订阅者 - 适用场景:
-1. 当一个抽象模型有两方面, 其中一个方面依赖于另一个方面. 将这两者封装在独立对象中以使它们可以各自独立地改变和复用.
-2. 当对一个对象的改变需要同时改变其他对象, 而不知道具体有多少对象有待改变.
-3. 当一个对象必须通知其他对象, 而它又不能假定其他对象是谁. 换言之, 你不希望这些对象是紧密耦合的. - 优点:
-1. 目标和观察者之间的抽象耦合最小
-2. 支持广播通信
from abc import ABCMeta, abstractmethod
class Observer(metaclass=ABCMeta): # 抽象订阅者
@abstractmethod
def update(self, notice): # notice 是一个Notice类的对象
pass
class Notice: # 抽象发布者
def __init__(self):
self.observers = []
def attach(self, obs):
self.observers.append(obs)
def detach(self, obs):
self.observers.remove(obs)
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, info):
self.__company_info = info
self.notify() # 关键代码, 推送给所有观察者
class Staff(Observer):
def __init__(self):
self.company_info = None
def update(self, notice):
self.company_info = notice.company_info
# Client
notice = StaffNotice("初始公司信息")
s1 = Staff()
s2 = Staff()
notice.attach(s1)
notice.attach(s2)
print(s1.company_info) # None
notice.company_info = "公司今年业绩非常好,给大家发奖金"
print(s1.company_info) # 被修改了
print(s2.company_info) # 被修改了
notice.detach(s2)
notice.company_info = "公司明天放假"
print(s1.company_info) # 被修改了
print(s2.company_info) # 没有被修改
3. 策略模式
- 内容: 定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换。本模式使得算法可独立于使用他们的客户而变化。
- 角色:
-1. 抽象策略(Strategy)
-2. 具体策略(ConcreteStrategy)
-3. 上下文(Context) - 优点:
-1. 定义了一系列可重用的算法和行为
-2. 消除了一些条件语句
-3. 可以提供相同行为的不同实现 - 缺点:
-1. 客户必须了解不同的策略
from abc import ABCMeta, abstractmethod
class Strategy(metaclass=ABCMeta):
@abstractmethod
def execute(self, data):
pass
class FastStrategy(Strategy):
def execute(self, data):
print("用较快的策略处理%s"%data)
class SlowStrategy(Strategy):
def execute(self, data):
print("用较慢的策略处理%s" % data)
class Context:
def __init__(self,data,strategy):
self.data = data
self.strategy = strategy
def set_strategy(self, strategy):
self.strategy = strategy
def do_strategy(self):
self.strategy.execute(self.data)
# Client
data = "[...]"
s1 = FastStrategy()
s2 = SlowStrategy()
context = Context(data,s1)
context.do_strategy()
context.set_strategy(s2)
context.do_strategy()
4. 模版方法模式
- 内容: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义改算法的某些特定步骤。
- 角色:
-1. 抽象类(AbstractClass):定义抽象的原子操作(钩子操作);实现一个模板方法作为算法的骨架。
-2. 具体类(ConcreteClass) :实现原子操作 - 适用场景:
-1. 一次性实现一个算法的不变的部分
-2. 各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复
-3. 控制子类扩展
from abc import ABCMeta,abstractmethod
from time import sleep
class Window(metaclass=ABCMeta):
@abstractmethod
def star(self):
pass
@abstractmethod
def repaint(self):
pass
@abstractmethod
def stop(self):
pass
def run(self): # 模板方法
self.star()
while True:
try:
self.repaint()
sleep(1)
except KeyboardInterrupt:
break
self.stop()
class MyWindow(Window):
def __init__(self,msg):
self.msg = msg
def star(self):
print("窗口开始运行")
def stop(self):
print("窗口结束运行")
def repaint(self):
print(self.msg)
MyWindow("Hello World").run()
总结
提示:这里对文章进行总结: