23种设计模式Python版

目录

    • 创建型模式
      • 简单工厂模式
      • 工厂方法模式
      • 抽象工厂模式
      • 单例模式
      • 原型模式
      • 建造者模式
    • 结构型模式
      • 适配器模式
      • 桥接模式
      • 组合模式
      • 装饰器模式
      • 外观模式
      • 享元模式
      • 代理模式
    • 行为型模式
      • 职责链模式
      • 命令模式
      • 解释器模式
      • 迭代器模式
      • 中介者模式
      • 备忘录模式
      • 观察者模式
      • 状态模式
      • 策略模式
      • 模板方法模式
      • 访问者模式
  • Reference

创建型模式

简单工厂模式

在这里插入图片描述

  • 实现
from abc import abstractmethod, ABCMeta

class Product(metaclass = ABCMeta):
    def __init__(self):
        pass

    @abstractmethod
    def do(self):
        pass

class ConcreteProductA(Product):
    def __init__(self):
        super().__init__()

    def do(self):
        print("[ConcreteProductA]do()")

class ConcreteProductB(Product):
    def __init__(self):
        super().__init__()

    def do(self):
        print("[ConcreteProductB]do()")

class SimpleFactory:
    @staticmethod
    def create_product(arg):
        if "A" == str.upper(arg):
            return ConcreteProductA()
        elif "B" == str.upper(arg):
            return ConcreteProductB()
        else:
            raise Exception(f"Unsupported: {arg}")
        
if __name__ == "__main__":
    product_a = SimpleFactory.create_product("A")
    product_a.do()

    product_b = SimpleFactory.create_product("b")
    product_b.do()

  • 优点
    简单工厂模式提供了专门的工厂类用于创建对象,将对象的创建和对象的使用分离开。客户端只需提供想要的产品属性,简单工厂就可以创建出来具体的产品供客户端使用(客户端不用关心创建逻辑)。
  • 缺点
    工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。系统扩展困难,一旦添加新产品就得修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
  • 适用场景
    工厂类负责创建的对象比较少,不会造成工厂方法中的业务逻辑太过复杂。

工厂方法模式

在这里插入图片描述

  • 实现
from abc import abstractmethod, ABCMeta

class Product(metaclass = ABCMeta):
    def __init__(self):
        pass

    @abstractmethod
    def do(self):
        pass

class ConcreteProductA(Product):
    def __init__(self):
        super().__init__()

    def do(self):
        print("[ConcreteProductA]do()")

class ConcreteProductB(Product):
    def __init__(self):
        super().__init__()

    def do(self):
        print("[ConcreteProductB]do()")

class Factory(metaclass = ABCMeta):
    def __init__(self):
        pass

    @abstractmethod
    def create_product(self):
        pass

class FactoryA(Factory):
    def __init__(self):
        super().__init__()

    def create_product(self):
        return ConcreteProductA()

class FactoryB(Factory):
    def __init__(self):
        super().__init__()

    def create_product(self):
        return ConcreteProductB()
        
if __name__ == "__main__":
    factoryA = FactoryA()
    productA = factoryA.create_product()
    productA.do()

    factoryB = FactoryB()
    productB = factoryB.create_product()
    productB.do()
  • 优点
    继承了简单工厂模式的优点,用户只需要关心所需产品对应的工厂。扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以,符合“开闭原则”。

  • 缺点
    每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度。

  • 使用场景
    数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。

抽象工厂模式

在这里插入图片描述
产品族:小米的手机+电视、华为的手机+电视
产品等级结构:手机的小米+华为,电视的小米+华为
增加产品族,比如OPPO的手机+电视,只需增加OPPO工厂及对应具体产品即可,符合“开闭原则”;但增加产品等级结构,比如耳机的小米+华为,就需要修改所有工厂,违反“开闭原则”。

from abc import abstractmethod, ABCMeta

class ProductA(metaclass = ABCMeta):
    def __init__(self):
        pass

    @abstractmethod
    def do(self):
        pass

class ConcreteProductA1(ProductA):
    def __init__(self):
        super().__init__()

    def do(self):
        print("[ConcreteProductA1]do()")

class ConcreteProductA2(ProductA):
    def __init__(self):
        super().__init__()

    def do(self):
        print("[ConcreteProductA2]do()")

class ProductB(metaclass = ABCMeta):
    def __init__(self):
        pass

    @abstractmethod
    def do(self):
        pass

class ConcreteProductB1(ProductB):
    def __init__(self):
        super().__init__()

    def do(self):
        print("[ConcreteProductB1]do()")

class ConcreteProductB2(ProductB):
    def __init__(self):
        super().__init__()

    def do(self):
        print("[ConcreteProductB2]do()")

class Factory(metaclass = ABCMeta):
    def __init__(self):
        pass

    @abstractmethod
    def create_productA(self):
        pass

    @abstractmethod
    def create_productB(self):
        pass

class Factory1(Factory):
    def __init__(self):
        super().__init__()

    def create_productA(self):
        return ConcreteProductA1()
    
    def create_productB(self):
        return ConcreteProductB1()

class Factory2(Factory):
    def __init__(self):
        super().__init__()

    def create_productA(self):
        return ConcreteProductA2()
    
    def create_productB(self):
        return ConcreteProductB2()
        
if __name__ == "__main__":
    factory1 = Factory1()
    productA1 = factory1.create_productA()
    productB1 = factory1.create_productB()
    productA1.do()
    productB1.do()

    factory2 = Factory2()
    productA2 = factory2.create_productA()
    productB2 = factory2.create_productB()
    productA2.do()
    productB2.do()

单例模式

在这里插入图片描述

class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance
        
if __name__ == "__main__":
    singleton1 = Singleton(1, x = 1)
    singleton2 = Singleton(2, x = 2)
    print(id(singleton1) == id(singleton2))

原型模式

在这里插入图片描述
浅克隆
在这里插入图片描述

深克隆
在这里插入图片描述

from abc import ABCMeta, abstractmethod
import copy

class Prototype(metaclass = ABCMeta):
    @abstractmethod
    def clone(self):
        pass

class PrototypeA(Prototype):
    def clone(self):
        return copy.copy(self)
    
class PrototypeB(Prototype):
    def clone(self):
        return copy.copy(self)
        
if __name__ == "__main__":
    prototypeA = PrototypeA()
    prototypeACopy = prototypeA.clone()

建造者模式

在这里插入图片描述

from abc import ABCMeta, abstractmethod

class Product:
    def __init__(self, a = None, b = None, c = None):
        self.a = a
        self.b = b
        self.c = c

    def __str__(self):
        return f"Product[a={self.a}, b={self.b}, c={self.c}]"

class Builder(metaclass = ABCMeta):
    @abstractmethod
    def buildA(self):
        pass

    @abstractmethod
    def buildB(self):
        pass

    @abstractmethod
    def buildC(self):
        pass

    @abstractmethod
    def getResult(self):
        pass

class ConcreteBuilder(Builder):
    def __init__(self):
        self.product = Product()

    def buildA(self):
        self.product.a = "A"
        print(f"build part {self.product.a}")

    def buildB(self):
        self.product.b = "B"
        print(f"build part {self.product.b}")

    def buildC(self):
        self.product.c = "C"
        print(f"build part {self.product.c}")

    def getResult(self):
        return self.product

class Director:
    def __init__(self, builder):
        self.builder = builder
    
    def construct(self):
        self.builder.buildA()
        self.builder.buildB()
        self.builder.buildC()
        return self.builder.getResult()

        
if __name__ == "__main__":
    builder = ConcreteBuilder()
    director = Director(builder)
    product = director.construct()
    print(product)

结构型模式

适配器模式

我的笔记本电脑的工作电压是20V,而我国的家庭用电是220V,如何让20V的笔记本电脑能够在220V的电压下工作?答案是引入一个电源适配器(AC Adapter),俗称充电器或变压器。
在这里插入图片描述
适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作。以电源适配器(Adapter)为例,Target是电脑目前支持的22V接口,Adaptee是220V插口。

对象适配器
在这里插入图片描述

from abc import ABCMeta, abstractmethod

class Target(metaclass = ABCMeta):
    @abstractmethod
    def request(self):
        print("can use 20V")

class Adaptee:
    def specificRequest(self):
        print("can use 220V")

class Adapter(Target):
    def __init__(self):
        self.adaptee = Adaptee()
    
    def request(self):
        print("Before")
        super().request()
        print()

        print("Now")
        print(f"Adapter, converting from 20V to 220V, ... , done")
        self.adaptee.specificRequest()
        
if __name__ == "__main__":
    adapter = Adapter()
    adapter.request()

类适配器
在这里插入图片描述

from abc import ABCMeta, abstractmethod

class Target(metaclass = ABCMeta):
    @abstractmethod
    def request(self):
        print("can use 20V")

class Adaptee:
    def specificRequest(self):
        print("can use 220V")

class Adapter(Target, Adaptee):
    def request(self):
        print("Before")
        super().request()
        print()

        print("Now")
        print(f"Adapter, converting from 20V to 220V, ... , done")
        self.specificRequest()  # super().specificRequest()
        
if __name__ == "__main__":
    adapter = Adapter()
    adapter.request()

桥接模式

将一个事物的两个维度分离,使其都可以独立地变化。

在这里插入图片描述

from abc import ABCMeta, abstractmethod

class Shape(metaclass = ABCMeta):
    def __init__(self, color):
        self.color = color

    @abstractmethod
    def draw(self):
        pass

class Rectangle(Shape):
    def draw(self):
        self.shape_name = "rectangle"
        self.color.paint()
        print(f"draw a {self.color.color_name} {self.shape_name}")

class Circle(Shape):
    def draw(self):
        self.shape_name = "circle"
        self.color.paint()
        print(f"draw a {self.color.color_name} {self.shape_name}")

class Color(metaclass = ABCMeta):
    @abstractmethod
    def paint(self):
        pass

class Red(Color):
    def paint(self):
        self.color_name = "red"

class Blue(Color):
    def paint(self):
        self.color_name = "blue"
        
if __name__ == "__main__":
    shape = Circle(Red())
    shape.draw()

组合模式

将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

在这里插入图片描述

from abc import ABCMeta, abstractmethod

class AbstractFile(metaclass = ABCMeta):
    @abstractmethod
    def add(self, file):
        pass

    @abstractmethod
    def remove(self, file):
        pass

    @abstractmethod
    def getChild(self, i):
        pass

    @abstractmethod
    def traverse(self, deep):
        pass

class TextFile(AbstractFile):
    def __init__(self, name):
        self.name = name

    def add(self, file):
        raise Exception("unsupported")
    
    def remove(self, file):
        raise Exception("unsupported")
    
    def getChild(self, i):
        raise Exception("unsupported")
    
    def traverse(self, deep):
        for i in range(deep):
            print("\t", end="")
        print(f"text:{self.name}")

class ImageFile(AbstractFile):
    def __init__(self, name):
        self.name = name

    def add(self, file):
        raise Exception("unsupported")
    
    def remove(self, file):
        raise Exception("unsupported")
    
    def getChild(self, i):
        raise Exception("unsupported")
    
    def traverse(self, deep):
        for i in range(deep):
            print("\t", end="")
        print(f"image:{self.name}")

class Folder(AbstractFile):
    def __init__(self, name):
        self.name = name
        self.file_list = []

    def add(self, file):
        self.file_list.append(file)
    
    def remove(self, file):
        self.file_list.remove(file)
    
    def getChild(self, i):
        return self.file_list.index(i)
    
    def traverse(self, deep):
        for i in range(deep):
            print("\t", end="")
        print(self.name)

        for f in self.file_list:
            f.traverse(deep + 1)
        
if __name__ == "__main__":
    folder1 = Folder("folder1")
    file1 = TextFile("t1.txt")
    file2 = ImageFile("i1.png")
    folder1.add(file1)
    folder1.add(file2)

    folder2 = Folder("folder2")
    file3 = TextFile("t2.txt")
    file4 = ImageFile("i2.png")
    folder2.add(file3)
    folder2.add(file4)
    folder1.add(folder2)

    folder1.traverse(0)

装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。它是作为现有的类的一个包装。
在这里插入图片描述

from abc import ABCMeta, abstractmethod

class Component(metaclass = ABCMeta):
    @abstractmethod
    def operation(self):
        pass

class ConcreteComponent(Component):
    def operation(self):
        print("ConcreteComponent.operation()")

class Decorator(Component):
    def __init__(self, component):
        self.component = component

    def operation(self):
        self.component.operation()

class ConcreteDecoratorA(Decorator):
    def __init__(self, component, state):
        super().__init__(component)
        self.state = state

    def operation(self):
        super().operation()
        print(f"state: {self.state}")

class ConcreteDecoratorB(Decorator):
    def operation(self):
        super().operation()
        self.added_behavior()
    
    def added_behavior(self):
        print("ConcreteDecoratorB.added_behavior()")
    
        
if __name__ == "__main__":
    component = ConcreteComponent()
    decoratorA = ConcreteDecoratorA(component, "Normal")
    decoratorA.operation()

    decoratorB = ConcreteDecoratorB(component)
    decoratorB.operation()

外观模式

外观模式中,一个子系统的外部与其内部的通信通过一个统一的外观类进行,外观类将客户类与子系统的内部复杂性分隔开,使得客户类只需要与外观角色打交道,而不需要与子系统内部的很多对象打交道。
在这里插入图片描述

在这里插入图片描述

class CPU:
    def start(self):
        print("cpu start...")

    def stop(self):
        print("cpu stop...")

class Memory:
    def start(self):
        print("memory start...")

    def stop(self):
        print("memory stop...")

class Disk:
    def start(self):
        print("disk start...")

    def stop(self):
        print("disk stop...")

class Computer:
    def __init__(self):
        self.cpu = CPU()
        self.memory = Memory()
        self.disk = Disk()
    
    def start(self):
        self.cpu.start()
        self.memory.start()
        self.disk.start()

    def stop(self):
        self.cpu.stop()
        self.memory.stop()
        self.disk.stop()
        
if __name__ == "__main__":
    computer = Computer()
    computer.start()
    computer.stop()

享元模式

围棋棋子只有黑白棋两种(内部状态只有黑白,所有黑子共享黑内部状态,所有白子共享白内部状态。减少创建对象的数量),而每次落子坐标不同(外部状态)。
在这里插入图片描述

from abc import abstractmethod, ABCMeta

class IgoChessman(metaclass = ABCMeta):
    @abstractmethod
    def get_color(self):
        pass

    def display(self, coordinate):
        print(f"{self.get_color()}, {coordinate.x, coordinate.y}")

class BlackIgoChessman(IgoChessman):
    def get_color(self):
        return "black"
    
class WhiteIgoChessman(IgoChessman):
    def get_color(self):
        return "white"

class IgoChessmanFactory:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            cls._instance = super(IgoChessmanFactory, cls).__new__(cls)
        cls._instance.ht = {}
        cls._instance.ht["black"] = BlackIgoChessman()
        cls._instance.ht["white"] = WhiteIgoChessman()
        return cls._instance
    
    def getIgoChessman(self, color):
        return IgoChessmanFactory._instance.ht[color]
    
class Coordinate:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
if __name__ == "__main__":
    factory = IgoChessmanFactory()
    black1 = factory.getIgoChessman("black")
    white1 = factory.getIgoChessman("white")
    black2 = factory.getIgoChessman("black")
    white2 = factory.getIgoChessman("white")

    print(black1 is black2)
    print(white1 is white2)
    black1.display(Coordinate(1, 2))
    white1.display(Coordinate(3, 4))
    black2.display(Coordinate(8, 9))
    white2.display(Coordinate(4, 5))


代理模式

在这里插入图片描述
在这里插入图片描述

保护代理(Protect Proxy):控制对一个对象的访问,给不同的用户提供不同级别的使用权限。

在这里插入图片描述
在这里插入图片描述

from abc import abstractmethod, ABCMeta
import time

class Searcher(metaclass = ABCMeta):
    @abstractmethod
    def search(self, user_id, key_word):
        pass

class RealSearcher(Searcher):
    def search(self, user_id, key_word):
        print(f"[RealSearcher.search](use_id: {user_id}, key_word: {key_word}) and return 'what you want'")
    
class AccessValidator:
    def validate(self, user_id):
        print(f"[AccessValidator.validate]{user_id} has access to search!")

class Logger:
    def log(self, user_id):
        print(f"[Logger.log]{user_id} visit at {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))}")
    
class ProxySearcher(Searcher):
    def __init__(self):
        self.validator = AccessValidator()
        self.logger = Logger()
        self.searcher = RealSearcher()

    def search(self, user_id, key_word):
        self.validator.validate(user_id)
        self.searcher.search(user_id, key_word)
        self.logger.log(user_id)
        
if __name__ == "__main__":
    proxy = ProxySearcher()
    proxy.search("Tom", "iPhone")


行为型模式

职责链模式

在这里插入图片描述

职责链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
在这里插入图片描述

from abc import abstractmethod, ABCMeta

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

    def set_successor(self, successor):
        self.successor = successor

class GeneralManagerHandler(Handler):
    def handle_leave(self, day):
        if day <= 10:
            print("General manager approved %d days' leave." % day)
        else:
            print("No approval!")

class DepartmentManagerHandler(Handler):
    def handle_leave(self, day):
        if day <= 7:
            print("Department manager approved %d days' leave." % day)
        else:
            self.successor.handle_leave(day)

class ProjectManagerHandler(Handler):
    def handle_leave(self, day):
        if day <= 3:
            print("Project manager approved %d days' leave." % day)
        else:
            self.successor.handle_leave(day)
        
if __name__ == "__main__":
    projectManager = ProjectManagerHandler()
    departmentManager = DepartmentManagerHandler()
    generalManager = GeneralManagerHandler()

    projectManager.set_successor(departmentManager)
    departmentManager.set_successor(generalManager)

    projectManager.handle_leave(8)

命令模式

在这里插入图片描述

Invoker:开关
Command:电线
Receiver:电灯/排风扇
在这里插入图片描述
命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。

from abc import abstractmethod, ABCMeta

class Invoker:
    def __init__(self, wire):
        self.wire = wire

    def open(self):
        self.wire.execute()

class Wire(metaclass = ABCMeta):
    @abstractmethod
    def execute(self):
        pass

class LampWire(Wire):
    def __init__(self):
        self.lamp_receiver = LampReceiver()

    def execute(self):
        self.lamp_receiver.action()

class FanWire(Wire):
    def __init__(self):
        self.fan_wire = FanReceiver()

    def execute(self):
        self.fan_wire.do()

class LampReceiver:
    def action(self):
        print("open the lamp")

class FanReceiver:
    def do(self):
        print("open the fan")    
        
if __name__ == "__main__":
    invoker1 = Invoker(LampWire())
    invoker1.open()

    invoker2 = Invoker(FanWire())
    invoker2.open()

解释器模式

在这里插入图片描述

在这里插入图片描述

简化版四则运算解释器的实现(真正实现要搞定中缀表达式求解逻辑,封入Context中)

from abc import abstractmethod, ABCMeta

class Expression(metaclass = ABCMeta):
   @abstractmethod
   def interpret(self, context):
        pass

class NumberExpression(Expression):
   def __init__(self, value):
      self.value = value

   def interpret(self, context):
      return self.value

class AddExpression(Expression):
   def __init__(self, left, right):
      self.left = left
      self.right = right

   def interpret(self, context):
      return self.left.interpret(context) + self.right.interpret(context)

class SubtractExpression(Expression):
   def __init__(self, left, right):
      self.left = left
      self.right = right

   def interpret(self, context):
      return self.left.interpret(context) - self.right.interpret(context)

class Context:
   pass




if __name__ == '__main__':
   expression = AddExpression(NumberExpression(10), SubtractExpression(NumberExpression(5), NumberExpression(2)))
   result = expression.interpret(Context())
   print(result)

迭代器模式

在软件开发中,我们经常需要使用聚合对象来存储一系列数据。聚合对象拥有两个职责:一是存储数据;二是遍历数据。从依赖性来看,前者是聚合对象的基本职责;而后者既是可变化的,又是可分离的。因此,可以将遍历数据的行为从聚合对象中分离出来,封装在一个被称之为“迭代器”的对象中,由迭代器来提供遍历聚合对象内部数据的行为,这将简化聚合对象的设计,更符合“单一职责原则”的要求。

迭代器模式(Iterator Pattern):提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示,其别名为游标(Cursor)。迭代器模式是一种对象行为型模式。

在迭代器模式结构中包含聚合和迭代器两个层次结构,考虑到系统的灵活性和可扩展性,在迭代器模式中应用了工厂方法模式,其模式结构如下图所示:

在这里插入图片描述

from abc import ABC, abstractmethod

class Aggregate(ABC):
   @abstractmethod
   def create_iterator(self):
      pass


class ConcreteAggregate(Aggregate):
   def __init__(self):
      self.data = list(range(1, 6))
      self.idx = 0

   def create_iterator(self):
      return ConcreteIterator(self)


class Iterator(ABC):
   @abstractmethod
   def has_next(self):
      pass

   @abstractmethod
   def next(self):
      pass

class ConcreteIterator(Iterator):
    def __init__(self, aggregate):
        self.aggregate = aggregate

    def has_next(self):
        return self.aggregate.idx < len(self.aggregate.data)

    def next(self):
        data = self.aggregate.data[self.aggregate.idx]
        self.aggregate.idx += 1
        return data

if __name__ == '__main__':
      aggregate = ConcreteAggregate()
      iterator = aggregate.create_iterator()
      while iterator.has_next():
         print(iterator.next())

中介者模式

如果在一个系统中对象之间存在多对多的相互关系,我们可以将对象之间的一些交互行为从各个对象中分离出来,并集中封装在一个中介者对象中,并由该中介者进行统一协调,这样对象之间多对多的复杂关系就转化为相对简单的一对多关系。通过引入中介者来简化对象之间的复杂交互,中介者模式是“迪米特法则”的一个典型应用。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

以微信群发消息为例(多人两两交互变为一对多交互),实现如下:

from abc import ABC, abstractmethod

class Mediator(ABC):
   @abstractmethod
   def send_msg(self, colleague, msg):
      pass


class ConcreteMediator(Mediator):
   def send_msg(self, colleague, msg):
      print(f"[{colleague.name}] {msg}")

class Colleague(ABC):
   @abstractmethod
   def __init__(self, name, mediator):
      self.mediator = mediator
      self.name = name

   @abstractmethod
   def send_msg(self, msg):
      pass 

class ConcreteColleague(Colleague):
   def __init__(self, name, mediator):
      super().__init__(name, mediator)

   def send_msg(self, msg):
      self.mediator.send_msg(self, msg)

if __name__ == '__main__':
   mediator = ConcreteMediator()
   colleague1 = ConcreteColleague("Jack", mediator)
   colleague2 = ConcreteColleague("Marry", mediator)
   colleague1.send_msg("Are you ok")
   colleague2.send_msg("Happy")
   

备忘录模式

备忘录模式提供了状态恢复机制,比如下棋的悔棋就可以用备忘录模式实现。
在这里插入图片描述

在这里插入图片描述

class Chessman:
   def __init__(self, label, x, y):
      self.label = label
      self.x = x
      self.y = y

   def set_x(self, x):
      self.x = x

   def set_y(self, y):
      self.y = y

   def display(self):
      print(f"[{self.label}] x = {self.x}, y = {self.y}")

   def save(self):
      return Memo(self.label, self.x, self.y)

   def restore(self, memo):
      self.label = memo.label
      self.x = memo.x
      self.y = memo.y

class Memo:
   def __init__(self, label, x, y):
      self.label = label
      self.x = x
      self.y = y

class MemoManager:
   def __init__(self):
      self.memos = []
   
   def add_memo(self, memo):
      self.memos.append(memo)

   def pop_memo(self):
      print("Try to undo...")
      if(len(self.memos) < 1):
         print("The location now is original, so you cannot undo!")
         return None
      return self.memos.pop()

if __name__ == '__main__':
   manager = MemoManager()
   chessman = Chessman('CAR', 1, 1)
   
   chessman.display()
   memo = chessman.save()
   manager.add_memo(memo)
   
   chessman.set_y(4)
   chessman.display()
   memo = chessman.save()
   manager.add_memo(memo)

   chessman.set_x(6)
   chessman.display()

   memo = manager.pop_memo()
   if memo is not None:
      chessman.restore(memo)
      chessman.display()

   memo = manager.pop_memo()
   if memo is not None:
      chessman.restore(memo)
      chessman.display()

   memo = manager.pop_memo()
   if memo is not None:
      chessman.restore(memo)
      chessman.display()
   

观察者模式

“红灯停,绿灯行”,在日常生活中,交通信号灯装点着我们的城市,指挥着日益拥挤的城市交通。当红灯亮起,来往的汽车将停止;而绿灯亮起,汽车可以继续前行。在这个过程中,交通信号灯是汽车(更准确地说应该是汽车驾驶员)的观察目标,而汽车是观察者。随着交通信号灯的变化,汽车的行为也将随之而变化,一盏交通信号灯可以指挥多辆汽车。

观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。

在这里插入图片描述

from abc import ABC, abstractmethod

class Observer(ABC):
   def __init__(self, name):
      self.name = name

   @abstractmethod
   def update(msg):
      pass

class ConcreteObserver(Observer):
   def __init__(self, name):
      super().__init__(name)

   def update(self, msg):
      print(f"[{self.name}]: {msg}")

class Project(ABC):
   @abstractmethod
   def add_observer(self, observer):
      pass

   @abstractmethod
   def delete_observer(self, observer):
      pass

   @abstractmethod
   def notify(self):
      pass

class ConcreteProject(Project):
   def __init__(self):
      self.observers = []

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

   def delete_observer(self, observer):
      self.observers.remove(observer)

   def notify(self, msg):
      for observer in self.observers:
         observer.update(msg)

if __name__ == '__main__':
   traffic_light = ConcreteProject()
   tom = ConcreteObserver("Tom")
   lucy = ConcreteObserver("Lucy")
   traffic_light.add_observer(tom)
   traffic_light.add_observer(lucy)
   traffic_light.notify("traffic light is red")

状态模式

在这里插入图片描述

在这里插入图片描述

点击循环调整屏幕尺寸,正常、更大、最大、正常……
在这里插入图片描述

from abc import ABC, abstractmethod

class State(ABC):
   @abstractmethod
   def display(self):
      pass

class NormalState(State):
   def display(self):
      print("Normal")

class LargerState(State):
   def display(self):
      print("Larger")

class LargestState(State):
   def display(self):
      print("Largest")

class Screen:
   def __init__(self):
      self.normal_state = NormalState()
      self.larger_state = LargerState()
      self.largest_state = LargestState()
      self.state = self.normal_state

   def on_click(self):
      if self.state is self.normal_state:
         self.state = self.larger_state
      elif self.state is self.larger_state:
         self.state = self.largest_state
      else:
         self.state = self.normal_state
      self.state.display()

if __name__ == '__main__':
   screen = Screen()
   screen.on_click()
   screen.on_click()
   screen.on_click()
   screen.on_click()

策略模式

在这里插入图片描述

from abc import ABC, abstractmethod

class Strategy(ABC):
   @abstractmethod
   def algorithm(self):
      pass

class ConcreteStategyA(Strategy):
   def algorithm(self):
      print("ConcreteStategyA")

class ConcreteStategyB(Strategy):
   def algorithm(self):
      print("ConcreteStategyB")

class Context:
   def set_stategy(self, strategy):
      self.strategy = strategy
   
   def algorithm(self):
      self.strategy.algorithm()

if __name__ == '__main__':
   context = Context()
   context.set_stategy(ConcreteStategyA())
   context.algorithm()

   context.set_stategy(ConcreteStategyB())
   context.algorithm()

模板方法模式

在这里插入图片描述

from abc import ABC, abstractmethod

class Game(ABC):
   def play(self):
      self.init()
      self.start()
      self.end()

   @abstractmethod
   def init(self):
      pass

   @abstractmethod
   def start(self):
      pass

   @abstractmethod
   def end(self):
      pass

class GameA(Game):
   def init(self):
      print("[GameA]init...")
   
   def start(self):
      print("[GameA]start...")

   def end(self):
      print("[GameA]end...")

class GameB(Game):
   def init(self):
      print("[GameB]init...")
   
   def start(self):
      print("[GameB]start...")

   def end(self):
      print("[GameB]end...")

if __name__ == '__main__':
   game_a = GameA()
   game_a.play()

   game_b = GameB()
   game_b.play()

访问者模式

访问者模式是一种较为复杂的行为型设计模式,它包含访问者和被访问元素两个主要组成部分,这些被访问的元素通常具有不同的类型,且不同的访问者可以对它们进行不同的访问操作。例如处方单中的各种药品信息就是被访问的元素,而划价人员和药房工作人员就是访问者。访问者模式使得用户可以在不修改现有系统的情况下扩展系统的功能,为这些不同类型的元素增加新的操作。
在这里插入图片描述
公司中有正式工和临时工,而HR和财务人员对工人的关注点不同,前者关心工时计算,后者关心工资计算。这个例子中,工人对应Element,HR和财务人员对应Visitor。实现如下:
在这里插入图片描述

from abc import ABC, abstractmethod

class Employee(ABC):
   @abstractmethod
   def accept(self, handler):
      pass

class FulltimeEmployee(Employee):
   def __init__(self, name, weekly_wage, work_time):
      self.name = name
      self.weekly_wage = weekly_wage
      self.work_time = work_time

   def accept(self, handler):
      handler.visit_fulltime_employee(self)

class ParttimeEmployee(Employee):
   def __init__(self, name, hourly_wage, work_time):
      self.name = name
      self.hourly_wage = hourly_wage
      self.work_time = work_time

   def accept(self, handler):
      handler.visit_parttime_employee(self)

class Department(ABC):
   @abstractmethod
   def visit_fulltime_employee(self, employee):
      pass
   
   @abstractmethod
   def visit_parttime_employee(self, employee):
      pass

class FinanceDepartment(Department):
   def visit_fulltime_employee(self, employee):
      if(employee.work_time > 40):
         week_wage = employee.weekly_wage + (employee.work_time - 40) * 100
      else:
         week_wage = employee.weekly_wage - (40 - employee.work_time) * 80
         if week_wage < 0:
            week_wage = 0
      print(f"Fulltime employee {employee.name}, salary = {week_wage} yuan")
   
   def visit_parttime_employee(self, employee):
      print(f"Parttime employee {employee.name}, salary = {employee.work_time * employee.hourly_wage} yuan")

class HRDepartment(Department):
   def visit_fulltime_employee(self, employee):
      print(f"Fulltime employee {employee.name}, work time = {employee.work_time} hours")
      if(employee.work_time > 40):
         print(f"Fulltime employee {employee.name},  overtime = {employee.work_time - 40} hours")
      else:
         print(f"Fulltime employee {employee.name},  vocation time = {40 - employee.work_time} hours")
      
   
   def visit_parttime_employee(self, employee):
      print(f"Parttime employee {employee.name}, work time = {employee.work_time} hours")

class EmployeeList:
   def __init__(self):
      self.employees = []

   def add(self, employee):
      self.employees.append(employee)

   def accept(self, handler):
      for employee in self.employees:
         employee.accept(handler)

if __name__ == '__main__':
   employee_list = EmployeeList()
   employee1 = FulltimeEmployee("employee1", 1000, 30)
   employee2 = FulltimeEmployee("employee2", 3000, 50)
   employee3 = ParttimeEmployee("employee3", 30, 15)
   employee4 = ParttimeEmployee("employee4", 20, 10)
   employee_list.add(employee1)
   employee_list.add(employee2)
   employee_list.add(employee3)
   employee_list.add(employee4)

   department1 = HRDepartment()
   department2 = FinanceDepartment()

   employee_list.accept(department1)
   employee_list.accept(department2)

Reference

[1] 史上最全设计模式导学目录(完整版)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/284513.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux安装rabbitmq

文章目录 前言一、下载安装包二、erlang1.安装依赖2.解压3.安装4.环境变量5.验证 三、rabbitmq1.安装依赖2.解压3.新建目录4.rabbitmq.env.conf5.rabbitmq.conf6.环境变量7.启动8.验证9.停止 四、安装web1.安装插件2.访问控制台界面 五、开机启动1.编写脚本2.设置开机启动3.测试…

服务器的TCP连接限制:如何优化并提高服务器的并发连接数?

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 欢迎关注公众号&#xff08;通过文章导读关注&#xff09;&#xff0c;发送【资料】可领取 深入理解 Redis 系列文章结合电商场景讲解 Redis 使用场景、中间件系列…

目标检测-One Stage-YOLOv1

文章目录 前言一、YOLOv1的网络结构和流程二、YOLOv1的损失函数三、YOLOv1的创新点总结 前言 前文目标检测-Two Stage-Mask RCNN提到了Two Stage算法的局限性&#xff1a; 速度上并不能满足实时的要求 因此出现了新的One Stage算法簇&#xff0c;YOLOv1是目标检测中One Stag…

TecoGAN视频超分辨率算法

1. 摘要 对抗训练在单图像超分辨率任务中非常成功&#xff0c;因为它可以获得逼真、高度细致的输出结果。因此&#xff0c;当前最优的视频超分辨率方法仍然支持较简单的范数&#xff08;如 L2&#xff09;作为对抗损失函数。直接向量范数作损失函数求平均的本质可以轻松带来时…

C++数据结构-栈

目录 栈顺序栈链栈 栈 栈是允许在表的一端进行插入和删除的线性表。表中允许插入删除的一端是栈顶&#xff0c;栈顶的当前位置是动态变化的&#xff1b;不允许插入和删除的一端是栈底&#xff0c;栈底的位置是不变的。当表中没有元素时称为空栈&#xff0c;插入数据的运算称为…

从 MySQL 的事务 到 锁机制 再到 MVCC

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、事务 1.1 含义 1.2 ACID 二、锁机制 2.1 锁分类 2.2 隔离级别 三、MVCC 3.1 介绍 3.2 隔离级别 3.3 原理 四、总结 前…

python使用动态规划解决不同路径问题

针对二维动态规划&#xff0c;还有一个问题就是关于求不同路径的实例&#xff0c;主要是说明在实际应用的场景中&#xff0c;要理解透彻实际问题的真正目的&#xff0c;就可以灵活实现代码编写。 对于求不同路径问题描述&#xff0c;对于一个机器人&#xff0c;处在一个mxn的网…

【Unity美术】Unity工程师对3D模型需要达到的了解【二】

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

基于JavaWeb实验室预约管理系统(源码+数据库+文档)

一、项目简介 本项目是一套基于JavaWeb实验室预约管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;e…

【MATLAB】鲸鱼算法优化混合核极限学习机(WOA-HKELM)时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 鲸鱼算法优化混合核极限学习机&#xff08;WOA-HKELM&#xff09;是一种时序预测算法&#xff0c;它结合了鲸鱼算法和混合核极限学习机&#xff08;HKELM&#xff09;的优点。以下是该算法…

Ts自封装WebSocket心跳重连

WebSocket是一种在单个TCP连接上进行全双工通信的协议&#xff0c;允许客户端和服务器之间进行双向实时通信。 所谓心跳机制&#xff0c;就是在长时间不使用WebSocket连接的情况下&#xff0c;通过服务器与客户端之间按照一定时间间隔进行少量数据的通信来达到确认连接稳定的手…

大模型微调LoRA训练与原理

1.什么是LoRA&#xff1f; LoRA的全称是LOW-RANK-ADAPTATION。是一种实现迁移学习的技术手段。 2. 矩阵的秩&#xff1f; 秩是一个向量空间的基向量的个数。例如&#xff1a;二维平面坐标系存在两个基向量&#xff0c;平面上任意的一个向量都可以使用这两个基向量进行线性表示…

PS制作淘宝主图

PS制作淘宝主图 1.制作主图主页1.1新建800x800画板1.2填充前景色&#xff1a;altdel1.3选择圆角矩形&#xff0c;半径501.4按住ALT&#xff0c;往下投复制 2.调色 1.制作主图主页 1.1新建800x800画板 1.2填充前景色&#xff1a;altdel 1.3选择圆角矩形&#xff0c;半径50 居中对…

矿用以太网通讯的电缆传输可行性分析

概述 井下通讯系统是煤矿安全及生产调度必不可少的设施&#xff0c;近年泄露技术、小灵通技术、无线对讲技术及WIFI技术相继应用于煤矿井下。WIFI技术在地面的短距离无线通讯中已有多年的应用&#xff0c;相对于其他的无线宽带技术来说比较成熟可靠。 “泄露”技术及低频穿透技…

VC2019更改文件名称代码

VC2019更改文件名称代码 效果代码 效果 华为手机拍摄的视频默认名称是“VID_20231213_111723”,图片名称是“IMG_20231213_111723”&#xff0c;需要批量将“VID”改为“IMG” 代码 代码&#xff08;C#&#xff09;&#xff1a; csharpStringBuilder sbnew StringBuilder()…

ROS TF坐标变换 - 静态坐标变换

目录 一、静态坐标变换&#xff08;C实现&#xff09;二、静态坐标变换&#xff08;Python实现&#xff09; 如前文所属&#xff0c;ROS通过广播的形式告知各模块的位姿关系&#xff0c;接下来详述这一机制的代码实现。 模块间的位置关系有两种类型&#xff0c;一种是相对固定…

使用spring boot实现异常的统一返回

在这个前后端分离的时代&#xff0c;一个 统一的数据格式非常重要。本次我们实现用spring boot实现一下返回给前端数据的统一格式&#xff0c;不再出现服务器500的错误。 新建一个spring boot项目&#xff0c;并导入knife4j的依赖。 写一个controller控制器&#xff0c;用来是…

Vue中全局事件总线的配置和原理

实现任意组件之间的通信 任意组件通信的原理&#xff1a; 1、实现任意组件之间的通信,需要一个傀儡。这个傀儡既能被vm访问到,也能被VueComponent访问。 2、VueComponent.prototype.proto Vue.prototype为图上1.0黄色的线路。是Vue让组件实例对象VueComponent可以访问到Vue原…

将学习自动化测试时的医药管理信息系统项目用idea运行

将学习自动化测试时的医药管理信息系统项目用idea运行 背景 学习自动化测试的时候老师的运行方式是把医药管理信息系统项目打包成war包后再放到tomcat的webapp中去运行&#xff0c;于是我想着用idea运行会方便点&#xff0c;现在记录下步骤方便以后查找最开始没有查阅资料&am…

【栈】根据模式串构造最小数字

import java.util.ArrayDeque; import java.util.Deque;/*** 思路&#xff1a;如果是字符‘I’直接对应的数字加入结果res中&#xff0c;如果是‘D’将对应的数字加入栈中。* 再次遇到‘I’先将对应的数字加入结果res中&#xff0c;然后再将栈中的元素从栈顶取出存放在* …
最新文章