23种设计模式Python版

news2024/11/28 11:57:51

目录

    • 创建型模式
      • 简单工厂模式
      • 工厂方法模式
      • 抽象工厂模式
      • 单例模式
      • 原型模式
      • 建造者模式
    • 结构型模式
      • 适配器模式
      • 桥接模式
      • 组合模式
      • 装饰器模式
      • 外观模式
      • 享元模式
      • 代理模式
    • 行为型模式
      • 职责链模式
      • 命令模式
      • 解释器模式
      • 迭代器模式
      • 中介者模式
      • 备忘录模式
      • 观察者模式
      • 状态模式
      • 策略模式
      • 模板方法模式
      • 访问者模式
  • 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.coloradmin.cn/o/1348928.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CUMT--Java复习--核心类

目录 一、装箱与拆箱 二、“”与equals 三、字符串类 1、String、StringBuffer、StringBuilder的区别 2、String类 3、StringBuffer类 4、StringBuilder类 四、类与类之间关系 一、装箱与拆箱 基本类型与对应封装类之间能够自动进行转换&#xff0c;本质就是Java的自…

【力扣题解】P105-从前序与中序遍历序列构造二叉树-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P105-从前序与中序遍历序列构造二叉树-Java题解&#x1f30f;题目描述&#x1f4a1;题…

论文速递|Management Science 11月文章合集(下)

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 编者按 在本系列文章中&#xff0c;我们梳理了运筹学顶刊Management Science11月份发布的47篇文章的基本信息&#xff0c;旨在帮助读者快速洞察行业最新动态。本文为第三部分。 文章1 ● 题目&#xff1a;…

Linux:apache优化(7)—— 访问控制

作用&#xff1a;为apache服务提供的页面设置客户端访问权限&#xff0c;为某个组或者某个用户加密访问&#xff1b; /usr/local/httpd/bin/htpasswd -c /usr/local/httpd/conf/htpasswd tarro1 #添加admin用户&#xff0c;可以在两个路径中间添加-c是新建文件删除原文件&#…

当你的电脑在安装Windows更新后出现问题时怎么办,这里提供办法

Windows更新通常会为你的电脑带来错误修复、安全补丁和新功能,但它们也可能会带来性能下降甚至引发恐慌的数据丢失等问题,从而适得其反。如果你在安装更新后发现了一些奇怪之处,你可以将其回滚,尝试重新启动。 Windows更新主要有两种:质量更新和功能更新。高质量的更新包…

16.综合项目实战

一、基础演练&#xff1a; 1、建库、建表 # 创建数据库 create database mysql_exampleTest; use mysql_exampleTest; # 学生表 CREATE TABLE Student( s_id VARCHAR(20), s_name VARCHAR(20) NOT NULL DEFAULT , s_birth VARCHAR(20) NOT NULL DEFAULT , s_sex VARC…

RocketMQ(Linux版本5.1.4)

1、停止之前的运行服务 [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# sh bin/mqshutdown namesrv No mqnamesrv running. [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# [roottssvr1-c1 rocketmq-all-4.7.0-bin-release]# [roottssvr1-c1 rocketmq-all-4.7.0-bin-r…

【编译原理】期末预习做题向I

新的一年希望可以成为更好的人嘿嘿&#xff01; 这一篇基本就是把 up 讲的题都截了一遍然后加了点自己的笔记啥的 O.o &#xff08;不妥的话会删掉的 qwq&#xff0c;希望没事嘿嘿&#xff09; 来源&#xff1a;混子速成 I. 绪论 记住组成部分 II. 前后无关文法和语言 1.…

[C#]OpenCvSharp结合yolov8-face实现L2CS-Net眼睛注视方向估计或者人脸朝向估计

源码地址&#xff1a; github地址&#xff1a;https://github.com/Ahmednull/L2CS-Net L2CS-Net介绍&#xff1a; 眼睛注视&#xff08;eye gaze&#xff09; 是在各种应用中使用的基本线索之一。 它表示用户在人机交互和开放对话系统中的参与程度。此外&#xff0c;它还被用…

zabbix监控基础

目录 一.zabbix概述 1.zabbix程序结构 2.Zabbix 监控原理 3.zabbix中核心的资源介绍 4.zabbix-agent支持的协议 二.zabbix监控环境搭建 1.zabbix服务器端 1) 基本配置 2) 安装 2.配置zabbix 1) 数据库设置 2) zabbix设置 3) ph…

轻量应用服务器与云服务器CVM对比——腾讯云

腾讯云轻量服务器和云服务器CVM该怎么选&#xff1f;不差钱选云服务器CVM&#xff0c;追求性价比选择轻量应用服务器&#xff0c;轻量真优惠呀&#xff0c;活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三…

Android 跨进程之间通信(IPC)方式之ContentProvider

Android 跨进程之间通信 Android 跨进程之间通信(IPC)方式之BroadcastReceiverAndroid 跨进程之间通信(IPC)方式之ContentProvider 文章目录 Android 跨进程之间通信前言一、ContentProvider 是什么&#xff1f;二、如何利用ContentProvider跨进程通信1.创建自定义ContentProv…

编译原理----FIRST集,LARST集,FIRSTVT集,LASTVT集

目录 FIRST集&#xff1a; LARST集&#xff1a; FIRSTVT集: LASTVT集&#xff1a; 构造规则&#xff1a; FIRST集&#xff1a; &#xff08;1&#xff09;A-->&#xff0c;若是终结符&#xff0c;那么FIRST&#xff08;A&#xff09;&#xff0c;若是非终结符&#xf…

啊哈c语言——逻辑挑战6:奔跑的小人

首先我们来设计这个小人&#xff1a; 将这个小人身体的三部分分为3行来分别表示&#xff1a; 第1行用一个大写字母O表示小人的脑袋。 第2行用左尖括号表示小人的右手&#xff0c;用大写字母H表示小人的身 体&#xff0c;用右尖括号>表示小人的右手。 第3行用两个大写字母…

集群部署篇--Redis 集群分片模式

文章目录 前言一、Redis 分片集群介绍1.1 介绍&#xff1a;1.2 工作机制&#xff1a;1.2.1 节点&#xff1a;1.2.2 槽 slot&#xff1a;1.2.3 故障转移&#xff1a; 二、Redis 分片集群搭建:2.1 配置文件&#xff1a;2.2 redis 部署&#xff1a;2.3 redis 集群创建&#xff1a;…

杂文月刊投稿方式论文发表要求

《杂文月刊》是由国家新闻出版总署批准的正规文学类期刊。主要内容取向&#xff1a;杂文、散文、小说、诗歌、漫画、文学评论、艺术评论、戏剧文化、地方文化、非遗文化、美学艺术、教育等历史、文化、文学、艺术类的文章。是广大专家、学者、教师、学子发表论文、交流信息的重…

2024年人工智能领域10大预测

2023年人工智能领域如果只能筛选一个关键词的话&#xff0c;恐怕非“大模型”莫属。大模型的发展在过去一年中&#xff0c;让各行各业发生了天翻地覆的变化&#xff0c;有企业因大模型而新生&#xff0c;有企业因大模型而消亡。企业的变迁跟技术迭代息息相关&#xff0c;而大模…

前端 js 基础(1)

js 结果输出 &#xff08;点击按钮修改文字 &#xff09; <!DOCTYPE html> <html> <head></head><body><h2>Head 中的 JavaScript</h2><p id"demo">一个段落。</p><button type"button" onclic…

【2023】hadoop基础介绍

&#x1f4bb;目录 Hadoop组成HDFSHDFS操作HDFS分布式文件存储NameNode元数据数据读写流程 YARN和MapReduceMapReduce&#xff1a;分布式计算YARN&#xff1a;资源管控调度YARN架构提交任务到**YARN中运行** Hadoop组成 hadoop安装教程可以看我这篇文章> &#x1f345;hado…

论数据资源持有权(上)

关注WX公众号&#xff1a; commindtech77&#xff0c; 获得数据资产相关白皮书下载地址 1. 回复关键字&#xff1a;数据资源入表白皮书 下载 《2023数据资源入表白皮书》 2. 回复关键字&#xff1a;光大银行 下载 光大银行-《商业银行数据资产会计核算研究报告》 3. 回复关键字…