目录
创建型模式
简单工厂模式
- 实现
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)