likes
comments
collection
share

python设计模式_Python六大原则,23种设计模式

作者站长头像
站长
· 阅读数 25

六大设计原则:

1、开放封闭原则:一个软件实体如类,模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展

2、里氏替换原则 :所有引用父类的地方必须透明的使用其子类对象,父类和子类参数和返回值都应该是一致的

3、依赖倒转原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。即针对接口编程,不要针对实现编程。

4、接口隔离原则:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。就像我们定义了一个动物类,会飞、会游泳、会跑,当我们实现实例的时候,我们实现老虎、但是老虎不会飞,这个飞就是臃肿的部分

5、迪米特法则:高内聚 低耦合

6、单一职责原则:不要存在多于一个导致类变更的原因,通常来讲:一个类只负责一项职责

设计模式

设计模式(Design Pattern)是几十年的开发人员经过长时间的试验和摸索,总结出来的一套 程序设计标准。它使得设计方案更加通俗易懂

  • 设计模式分类:
    • 创建型模式(5种):工厂方法模式抽象工厂模式创建者模式、(原型模式)、单例模式
    • 结构型模式(7种):适配器模式桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式
    • 行为型模式(11种):解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模版方法模式

一、创建型模式

1.单例模式介绍

1.内容:保证一个类只有一个实例,并提供一个访问他的全局访问点 2.使用场景:当类只能有一个实例而且客户可以从一个总所周知的访问点访问他 3.例: 比如Test是一个类,你创建两个对象a=Test(), b=Test()在单例模式下a,b两个对象相同 4.优点:

  • 对唯一实例的受控访问(比如写日志时的日志对象)
  • 数据库的连接
  • 单例模式相当于全局变量,单例模式防止了命名空间被污染
from abc import abstractmethod, ABCMeta

class Singleton(object):
    def __new__(cls, *args, **kwargs):           #new方法最后返回的是一个实例
        if not hasattr(cls, "_instance"):       #如果没有这个字段就调用父类创建
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance                     #永远返回的就是第一次创建的对象

class MyClass(Singleton):
    def __init__(self, name=None):
        if name:        #如果不传参数就不必赋值
            self.name = name
a = MyClass("a")        #第一次创建对象时传入的是"a",所以a.name=a
print(a)
print(a.name)

b = MyClass('b')       #第二次创建对象时传入的是"b",所以将name改成了b,所以b.name=b
print(b)
print(b.name)

print(a)                #在b创建实例化后name值已经改成了b所以 a.name=b
print(a.name)

# 注:可以看到实例a和b内存地址相同时一个实例
# <__main__.MyClass object at 0x00FBACB0>
# a
# <__main__.MyClass object at 0x00FBACB0>
# b
# <__main__.MyClass object at 0x00FBACB0>
# b

通过对程序的调试可以知道,我们使用的__new__的方法要比__init__先执行,而且是静态方法,可以直接.调用,使用完成,才是真正的创建了一个实例

通过上面的代码我们可以知道实际上_instance是随便写的,就是在类创建成功的时候,增加了一个类属性(其实就是那个新生成的对象),用于后面在生成类的时候,走过__new__的时候,判断下类属性是否存在,存在就不进行创建过程了,把之前的类属性(也就是新对象)返回回去即可,要没有,证明第一次构建,调用父类的__new__Create and return a new object,保存并返回,实现了生成对象的唯一。

@staticmethod # known case of __new__
def __new__(cls, *more): # known special case of object.__new__
    """ Create and return a new object.  See help(type) for accurate signature. """
    pass

2.工厂模式

内容:不直接向客户端(创建的对象)暴露对象创建的细节,而是通过一个工厂类来负责创建各种类的实例

  • 优点:
    • 隐藏了对象创建的实现细节
    • 客户端不需要修改代码  
  • 缺点:
    • 违反了单一职责原则,将创建逻辑集中到一个工厂类里
    • 当添加一个新产品时,需要修改工厂类代码,违法了开闭原则

在简单工厂函数中,我们可以在不同的method中,实现不同类的实例化,同时可以将一些不必要暴露的参数隐藏起来,像时间戳、指定的字符串、指定enable_yuebao的参数不同。

# 简单工厂模式
from abc import abstractmethod, ABCMeta

class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self, money):
        pass

class Alipay(Payment):
    def __init__(self, enable_yuebao=False):
        self.enable_yuebao = enable_yuebao

    def pay(self, money):
        if self.enable_yuebao:
            print("余额宝支付%s元" % money)
        else:
            print("支付宝支付%s元" % money)

class ApplePay(Payment):
    def pay(self, money):
        print("苹果支付%s元" % money)

#作用:用户在创建对象时不必关心需要传递那些参数
class PaymentFactory:
    def create_payment(self, method):
        if method == "alipay":
            return Alipay()
        elif method == "yuebao":
            return Alipay(True)
        elif method == "applepay":
            return ApplePay()
        else:
            raise NameError(method)

f = PaymentFactory()
p = f.create_payment("alipay")    #创建一个Alipay对象,这里创建对象时不必关心需要传递那些参数
p.pay(100)

3.工厂方法模式

内容:定义一个用于创建对象的接口(工厂接口),让子类决定实例化那个参品类

  • 角色:
    • 抽象工厂角色;
    • 具体工厂角色;
    • 抽象产品角色;
    • 具体产品角色;      
    • 特点:工厂方法模式相比简单工厂模式将每个具体参品都对应了一个具体工厂  
  • 适用场景:
    • 需要生产多种、大量复杂对象得时候
    • 需要降低耦合度的时候
    • 当系统中的参品类需要经常扩展的时候  
  • 优点:
    • 每个具体产品都对应一个具体工厂类,不需要修改工厂类代码
    • 隐藏了对象创建的实现细节  
  • 缺点:
    • 每增加一个具体的产品类,就必须增加一个对应的具体工厂类
# 工厂方法模式
from abc import abstractmethod, ABCMeta
class Payment(metaclass=ABCMeta):        #
    @abstractmethod
    def pay(self, money):
        pass
class Alipay(Payment):
    def pay(self, money):
        print("支付宝支付%s元" % money)
        
class ApplePay(Payment):
    def pay(self, money):
        print("苹果支付%s元"%money)

class PaymentFactory(metaclass=ABCMeta):
    @abstractmethod
    def create_payment(self):
        pass
    
class AlipayFactory(PaymentFactory):
    def create_payment(self):
        return Alipay()
    
class ApplePayFactory(PaymentFactory):
    def create_payment(self):
        return ApplePay()

af = AlipayFactory()
ali = af.create_payment()
ali.pay(120)

4.抽象工厂模式(解决多类产品)

内容: 定义一个工厂接口,让工厂子类来创建一系列相关或相互依赖的对象

  • 例: 生产一部手机,需要手机壳,CPU,操作系统三类对象进行组装,其中每类对象都有不同的种类。      对每个具体工厂分别生产一部手机所需要的三个对象 

  • 特点:相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品

  • 适用场景: 强调一系类相关的产品对象得设计以便进行联合使用时  

  • 优点:

    • 将客户端与具体类的实现相分离
    • 每个工厂创建了一个完整的产品系列,使得易于交换产品系列
    • 有利于产品的一致性(即:产品间的约束关系)
  • 缺点: 难以支持新种类的(抽象)产品,产品类新增(扩展)即可,但是在工厂类中需要修改代码(违反了开闭原则)

# 抽象工厂
from abc import abstractmethod, ABCMeta

# ------抽象产品------
class PhoneShell(metaclass=ABCMeta):
    @abstractmethod
    def show_shell(self):
        pass

class CPU(metaclass=ABCMeta):
    @abstractmethod
    def show_cpu(self):
        pass

class OS(metaclass=ABCMeta):
    @abstractmethod
    def show_os(self):
        pass


# ------抽象工厂------
class PhoneFactory(metaclass=ABCMeta):
    @abstractmethod
    def make_shell(self):
        pass

    @abstractmethod
    def make_cpu(self):
        pass

    @abstractmethod
    def make_os(self):
        pass

# ------具体产品------
class SmallShell(PhoneShell):
    def show_shell(self):
        print("普通手机小手机壳")

class BigShell(PhoneShell):
    def show_shell(self):
        print("普通手机大手机壳")

class AppleShell(PhoneShell):
    def show_shell(self):
        print("苹果手机壳")

class SnapDragonCPU(CPU):
    def show_cpu(self):
        print("骁龙CPU")

class MediaTekCPU(CPU):
    def show_cpu(self):
        print("联发科CPU")

class AppleCPU(CPU):
    def show_cpu(self):
        print("苹果CPU")

class Android(OS):
    def show_os(self):
        print("Android系统")

class IOS(OS):
    def show_os(self):
        print("iOS系统")

# ------具体工厂------
class MiFactory(PhoneFactory):
    def make_cpu(self):
        return SnapDragonCPU()
    def make_os(self):
        return Android()
    def make_shell(self):
        return BigShell()

class HuaweiFactory(PhoneFactory):
    def make_cpu(self):
        return MediaTekCPU()
    def make_os(self):
        return Android()
    def make_shell(self):
        return SmallShell()

class IPhoneFactory(PhoneFactory):
    def make_cpu(self):
        return AppleCPU()
    def make_os(self):
        return IOS()
    def make_shell(self):
        return AppleShell()

# ------客户端------
class Phone:
    def __init__(self, cpu, os, shell):
        self.cpu = cpu
        self.os = os
        self.shell = shell

    def show_info(self):
        print("手机信息:")
        self.cpu.show_cpu()
        self.os.show_os()
        self.shell.show_shell()

def make_phone(factory):
    cpu = factory.make_cpu()
    os = factory.make_os()
    shell = factory.make_shell()
    return Phone(cpu, os, shell)

p1 = make_phone(IPhoneFactory())
p1.show_info()

# 手机信息:
# 苹果CPU
# iOS系统
# 苹果手机壳

5.建造者模式

是将一个复杂对象的构造与表现进行分离,利用多个步骤进行创建,同一个构建过程可用于创建多个不同的表现 简单来说,就是将一个复杂对象实例化的过程,按照自己的想法,一步步设置参数,定制一个我们需要的对象 构建者模式一般由产品(product)、 Director(指挥官)和 Builder(建设者)构成 Builder 用于定义目标对象部件的方法和参数 Director 用于构造一个 Builder 的接口,由 Director 去指导 Builder 生成一个复杂的对象产品(product)

以购买一辆车( 包含:准备钱、看车、试驾、购买 4 个步骤)为例

优点:隐藏了一个产品的内部结构和装配的过程、将构造代码和表示代码分开、可以对构造过程进行更精细的控制

理解:就是Car是一个产品,builder就是其中的每个部门,每个部门分别为车进行构建,director的部分就是将前面各个部门的工作进行按照一定的顺序组装,最终得到一个产品对象。

from time import sleep
 
#首先,定义一个车的实体,并定义属性变量
class Car(object):
    def __init__(self):
        # 准备的钱
        self.money = None
 
        # 去哪里看车
        self.address = None
 
        # 试驾什么车
        self.car_name = None
 
        # 购买时间是
        self.buy_time = None
        
    def __str__(self):
        return "准备了:%s,去%s看车,试驾了%s,下单了,购买时间是:%s" % (self.money, self.address, self.car_name, self.buy_time)
    
#创建一个 Builder,实例化一个 Car 对象
class CarBuilder(object):
    def __init__(self):
        self.car = Car()
 
    def ready_money(self, money):
        """
        准备的金额
        :param money:
        :return:
        """
        self.car.money = money
        sleep(0.5)
        return self
 
    def see_car(self, address):
        """
        去哪里看车
        :param address:
        :return:
        """
        self.car.address = address
        sleep(0.5)
        return self
 
    def test_drive(self, car_name):
        """
        试驾了什么车
        :param car_name:
        :return:
        """
        self.car.car_name = car_name
        sleep(0.5)
        return self
 
    def buy_car(self, buy_time):
        """
        下单时间
        :param buy_time:
        :return:
        """
        self.car.buy_time = buy_time
        sleep(0.5)
        return self
    
#创建 Director,创建 build 方法,使用 Builder 一步步构建一个车对象并返回
class Director(object):
    def __init__(self):
        self.builder = None
 
    def build(self, builder): # 控制组装顺序
        self.builder = builder
        self.builder. ready_money("30万"). see_car("4S店"). test_drive("奥迪A4L"). buy_car("2022年8月1日")
 
        # 返回构建的对象
        return self.builder.car
    
if __name__ == '__main__':
    # 实例化一个构建者对象
    car_builder = CarBuilder()
    # 实例化一个负责人
    director = Director()
 
    # 构建的对象
    car = director.build(car_builder)
 
    print(car)

二、结构类模式

1.适配器模式

内容:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

1.适用场景:想使用一个已经存在的类,而他的接口不符合要求

2.两种实现方式:

  • 类适配器:使用多继承
# 当我们需要改动部分的代码很少的时候,我们直接多继承+复写方法即可
from abc import ABCMeta,abstractclassmethod

class Payment(metaclass=ABCMeta):
    @abstractclassmethod
    def pay(self,money):
        pass

class Alipay(Payment):
    def pay(self,money):
        print("阿里支付了{}元".format(money))

class Weixinpay(Payment):
    def pay(self,money):
        print("微信支付了{}元".format(money))

class Bankpay:
    def cost(self,money):
        print("银行卡支付{}元".format(money))

class NewBankPay(Payment,Bankpay):
    def pay(self,money):
        self.cost(money)

nb = NewBankPay()
nb.pay(100)
  • 对象适配器:使用组合
from abc import ABCMeta,abstractclassmethod

class Payment(metaclass=ABCMeta):
    @abstractclassmethod
    def pay(self,money):
        pass

class Alipay(Payment):
    def pay(self,money):
        print("阿里支付了{}元".format(money))

class Weixinpay(Payment):
    def pay(self,money):
        print("微信支付了{}元".format(money))

# 当存在多个需要进行适配的代码的时候(对象适配器)
class Bankpay:
    def cost(self,money):
        print("银行卡支付{}元".format(money))

class Applepay:
    def cost(self,money):
        print("苹果支付{}元".format(money))

class PaymentAdapter(Payment):
    def __init__(self,payment):
        self.payment = payment

    def pay(self,money):
        self.payment.cost(money)

nb = PaymentAdapter(Bankpay())
nb.pay(100)

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() 

将shape和Color进行解除耦合之后,我们可以对任意一个维度进行扩展,比之前的GreenLine的这种更容易维护。

应用场景:当事物有两个维度的表现,两个维度都可能扩展

优点:抽象和实现分离,优秀的扩展能力

3.组合模式

  1. 内容:将对象组合成树形状以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
  2. 角色:
    • 抽象组件
    • 叶子组件
    • 复合组件
    • 客户端
  3. 适用场景
    1. 表示对象的“部分-整体”层次结构(特别是结构是递归)
    2. 希望用户忽略组合对象和单个对象的不同,用户统一的使用组合结构中的所有对象
  4. 优点
    1. 定义了包含基本对象和组合对象的层次结构
    2. 简化了客户端的代码,即客户端可以一致的使用组合对象和单个对象
    3. 更容易增加新类型的组件
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. 角色:
    • 外观
    • 子系统类
  3. 优点:减少了系统相互依赖、提高了灵活性、提高了安全性
class CPU:
    def run(self):
        print("CPU开始工作")

    def stop(self):
        print("CPU停止工作")
        
class Disk:
    def run(self):
        print("硬盘开始工作")

    def stop(self):
        print("硬盘停止工作")
        
class Memory:
    def run(self):
        print("内存开始工作")

    def stop(self):
        print("内存停止工作")


class Computer:
    def __init__(self):
        self.CPU = CPU()
        self.Disk = Disk()
        self.Memory = Memory()
        
    def run(self):
        self.CPU.run()
        self.Disk.run()
        self.Memory.run()
    
    def stop(self):
        self.CPU.stop()
        self.Disk.stop()
        self.Memory.stop()

computer = Computer()
computer.run()
computer.stop()

5.代理模式

  1. 内容: 为其他对象提供一种代理以控制对这个对象的访问.
  2. 应用场景:
    • 远程代理: 为远程的对象提供代理,我们常用的orm框架其实就是远程代理模式
    • 虚代理: 根据需要创建很大的对象
    • 保护代理: 控制对原始对象的访问, 用于对象有不同访问权限时
  3. 角色
    • 抽象实体
    • 实体
    • 代理
  4. 优点
    • 远程代理:可以隐藏对象位于远程地址空间的事实
    • 虚代理:可以进行优化,例如根据要求创建对象
    • 保护代理:允许在访问一个对象时有一些附加的业务处理
from abc import ABCMeta,abstractclassmethod
class Subject():
    @abstractclassmethod
    def get_content(self):
        pass

    @abstractclassmethod
    def set_content(self,content):
        pass

class RealSubject(Subject):
    def __init__(self,filename):
        self.filename = filename
        f = open(self.filename,"r",encoding="utf-8")
        self.content = f.read()
        f.close()

    def get_content(self):
        return self.content

    def set_content(self,content):
        f = open(self.filename,"w",encoding="utf-8")
        f.write(content)
        f.close()

"""
这种方式的缺陷是,当我们实例化了对象之后,我们的self.content就会保存在内存中,文件过大,就会影响性能,使用虚代理解决
subj = RealSubject("text.txt")
subj.get_content()
"""

class VirtualProxy(Subject):
    def __init__(self,filename):
        self.filename = filename
        self.subj = None

    def get_content(self):
        if not self.subj:
            self.subj = RealSubject(self.filename)
        return self.subj.get_content()

    def set_content(self,content):
        if not self.subj:
            self.subj = RealSubject(self.filename)
        return self.subj.set_content(content)

# 保护代理
class ProtectedProxy(Subject):
    def __init__(self,filename):
        self.subj = RealSubject(filename)
    
    def get_content(self):
        return self.subj.get_content()

    def set_content(self,content):
        raise PermissionError("无权限处理此文件")

# 并没有创建真正的RealSubject对象,不会占用太多内存
subj = VirtualProxy("text.txt")
print(subj.get_content())

三、行为型模式

1.责任链模式

1.内容: 使多个对象都有机会处理请求, 从而避免请求的发送者和接受者之间的耦合关系. 将这些对象连城一条链, 并沿着这条链传递该请求, 直到有一个对象处理它为止.

2.角色:

  • 抽象处理者(Handler)
  • 具体处理者(ConcreteHandler)
  • 客户端(Client)

3.适用场景

  • 有多个对象可以处理一个请求,哪个对象处理由运行时决定
  • 在不明确接受者的情况下,向多个对象中的一个提交一个请求
  • 爬虫scrapy的pipeline处理

4.优点

  • 降低耦合度:一个对象无需知道是其他哪一个对象处理的他的请求
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.内容: 定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时, 所有依赖于它的对象都能得到通知并被自动更新. 观察者模式又称"发布-订阅"模式

2.角色:

  • 抽象主题(Subject)
  • 具体主题(ConcreteSubject) – 发布者
  • 抽象观察者(Observer)
  • 具体观察者(ConcreteObserver) – 订阅者

3.适用场景:

  • 当一个抽象模型有两方面, 其中一个方面依赖于另一个方面. 将这两者封装在独立对象中以使它们可以各自独立地改变和复用.

  • 当对一个对象的改变需要同时改变其他对象, 而不知道具体有多少对象有待改变.

  • 当一个对象必须通知其他对象, 而它又不能假定其他对象是谁. 换言之, 你不希望这些对象是紧密耦合的.

4.优点:

  • 目标和观察者之间的抽象耦合最小
  • 支持广播通信
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.内容: 定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换。本模式使得算法可独立于使用他们的客户而变化。

2.角色:

  • 抽象策略(Strategy)
  • 具体策略(ConcreteStrategy)
  • 上下文(Context)

3.优点:

  • 定义了一系列可重用的算法和行为
  • 消除了一些条件语句
  • 可以提供相同行为的不同实现

4.缺点:

  • 客户必须了解不同的策略
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.内容: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义改算法的某些特定步骤。

2.角色:

  • 抽象类(AbstractClass):定义抽象的原子操作(钩子操作);实现一个模板方法作为算法的骨架。
  • 具体类(ConcreteClass) :实现原子操作

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()
转载自:https://juejin.cn/post/7110103853957120036
评论
请登录