33.设计模式

设计模式

设计模式是一种编程套路,可以极大的方便程序的开发

最常见、最经典的设计模式,就是我们所学习的面向对象了。

除了面向对象,在编程中也有很多既定的套路可以方便开发,我们称之为设计模式:

  • 单例、工厂模式
  • 建造者、责任链、状态、备忘录、解释器、访问者、观察者、中介、模板、代理模式等等模式

单例模式

class Tool:

  pass

t1 = Tool()

t2 = Tool()

如上:创建类的实例后,就可以得到一个完整、独立的类对象,它们的内存地址是不同的

某些场景下,我们需要一个类无论获取多少次类对象,都仅仅提供一个具体的实例

用以节省创建类对象的开销和内存开销,比如某些工具类,仅需要1个实例,即可在各处使用,这就是单例模式所实现的效果。

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在

在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场

  • 定义:保证一个类只有一个实例,并提供一个访问它的全局访问点
  • 适合场景:当一个类只能有一个实例,而客户可以从一个众所周知的访问点访问它时
class StrTools:
    pass

s1 = StrTools()
s2 = StrTools()
print(s1)
print(s2)
<__main__.StrTools object at 0x000001FF12C219D0>
<__main__.StrTools object at 0x000001FF12C23950>
# 单实例对象引用
from my_package.str_tools import str_tool

s1 = str_tool
s2 = str_tool
print(id(s1))
print(id(s2))
2195043304224
2195043304224

工厂模式

当需要大量创建一个类的实例的时候,可以使用工厂模式

即,从原生的使用类的构造去创建对象的形式迁移到,基于工厂模式提供的方法去创建对象的形式

使用工厂类的方法去创建具体的类对象

优点:

  • 大批量创建对象的时候有统一的入口,易于代码维护
  • 当发生修改,仅修改工厂类的创建方法即可
  • 符合现实世界的模式,即由工厂来制作产品(对象)
class Person:
    pass

class Worker(Person):
    pass

class Student(Person):
    pass

class Teacher(Person):
    pass

class PersonFactory:
    def get_person(self, p_type):
        if p_type == "w":
            return Worker()
        elif p_type == "s":
            return Student()
        else:
            return Teacher()

if __name__ == '__main__':
    pf = PersonFactory()
    worker = pf.get_person("w")
    stu = pf.get_person("s")
    teacher = pf.get_person("t")

策略模式

  • 定义一系列的算法把它们一个个封装起来,并且使它们可相互替换.该模式使得算法可独立于使用它的客户而变化
  • 许多相关的类仅仅是行为有异,需使用一个算法的不同变体,算法使用了客户端无需知道的数据,一个类中的多个行为以多个条件语句存在可以将其封装在不同的策略类中
  • 优点:定义了一系列可重用的算法和行为,消除了一些条件语句,可提供相同行为的不同实现
  • 缺点:客户必须了解不同的策略,策略与上下文之间的通信开销,增加了对象的数目
class c1:
    def go(self):
        return 1

class c2:
    def go(self):
        return 2

if __name__ == '__main__':
    type = int(input('请输入要用的算法(1/2):'))
    if type == 1:
        print(c1().go())
    elif type == 2:
        print(c2().go())
1

观察者模式

  • 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并被自动更新.观察者模式又称为’发布订阅’模式
  • 适用场景: 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,这时候将两者封装在独立的对象中以使它们各自独立的改变和复用
    • 当一个对象的改变需要同时改变其他对象,而且不知道具体有多少对象以待改变
    • 当一个对象必须通知其他对象,而又不知道其他对象是谁,即这些对象之间是解耦的
  • 优点: 目标和观察者之间的耦合最小,支持广播通信
  • 缺点:多个观察者之间互不知道对方的存在,因此一个观察者对主题的修改可能造成错误的更新
class Boss:
    def __init__(self):
        self.observers = []
        self.command = ''

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

    def notify(self):
        for ob in self.observers:
            ob.message()  # 调用对象的update方法

class Employee():
    def __init__(self, name, boss):
        self.name = name
        self.boss = boss

    def message(self):
        print(f'{self.name},你的老板发来命令:{self.boss.command}')

if __name__ == '__main__':
    boss = Boss()
    zs = Employee('张三', boss)
    boss.attach(zs)
    boss.command = '你被开除了'
    boss.notify()
张三,你的老板发来命令:你被开除了