前言
山本无忧,因雪白头。水本无愁,因风起皱——《我欲封天》
设计模式不是必须的,不需要强迫自己使用设计模式。如果系统复杂了不知道怎么处理,可以看看设计模式中哪个可以帮帮。
\;\\\;\\\;
简单的设计模式
1抽象工厂
产品类有一颗树,工厂也有一颗树,最高层的工厂直接产生最高层的产品就行。
调用的时候直接调用最高层的产品函数,只是创建的是new第二层、第三层的产品。
concrete具体的,discreet谨慎的
from __future__ import annotations #这行必须放开头
from abc import ABC, abstractmethod
#第一层的工厂
class Factory(ABC):
@abstractmethod
def create_a(self) -> ProductA:
pass
@abstractmethod
def create_b(self) -> ProductB:
pass
#第二层的工厂
class ConcreteFactory1(Factory):
def create_a(self) -> ProductA:
return ConcreteProductA1() #创建第二层的产品
def create_b(self) -> ProductB:
return ConcreteProductB1() #创建第二层的产品
#第二层的工厂
class ConcreteFactory2(Factory):
def create_a(self) -> ProductA:
return ConcreteProductA2() #创建第二层的产品
def create_b(self) -> ProductB:
return ConcreteProductB2() #创建第二层的产品
#第一层的产品
class ProductA(ABC):
@abstractmethod
def run(self) -> str:
pass
#第二层的产品
class ConcreteProductA1(ProductA):
def run(self) -> str:
return "ConcreteProductA1:run()"
#第二层的产品
class ConcreteProductA2(ProductA):
def run(self) -> str:
return "ConcreteProductA2:run()"
#第一层的产品
class ProductB(ABC):
@abstractmethod
def exec(self) -> None:
pass
@abstractmethod
def another_exec(self, collaborator: ProductA) -> None: #collaborator注解,用来避免错误
pass
#第二层的产品
class ConcreteProductB1(ProductB):
def exec(self) -> str:
return "ConcreteProductB1:exec()"
def another_exec(self, collaborator: ProductA) -> str:
result = collaborator.run()
print(result)
return f"ConcreteProductB1:another_exec()"
#第二层的产品
class ConcreteProductB2(ProductB):
def exec(self) -> str:
return "ConcreteProductB2:exec()"
def another_exec(self, collaborator: ProductA) -> str:
result = collaborator.run()
print(result)
return f"ConcreteProductB2:another_exec()"
#客户代码
def client_code(factory: Factory) -> None:
product_a = factory.create_a()
product_b = factory.create_b()
#执行产品B的函数,其中又会调用产品A的函数
print(f"{product_b.exec()}")
print(f"{product_b.another_exec(product_a)}", end="")
def main():
#创建工厂1并执行
client_code(ConcreteFactory1())
print("\n")
# 创建工厂1并执行
client_code(ConcreteFactory2())
if __name__ == "__main__":
main()
\;\\\;\\\;
2工厂方法
结构更简单,适合单一类型产品
只在第二层、第三层才create,而抽象工厂第一层就create了
from __future__ import annotations
from abc import ABC, abstractmethod
#第一层工厂
class Factory(ABC):
@abstractmethod
def create(self):
pass
def exec(self) -> str:
product = self.create()
result = f"{product.run()}"
return result
#第二层工厂
class ConcreteFactory1(Factory):
def create(self) -> Product:
return ConcreteProduct1() #创建第二层产品
#第二层工厂
class ConcreteFactory2(Factory):
def create(self) -> Product:
return ConcreteProduct2() #创建第二层产品
#第一层产品
class Product(ABC):
@abstractmethod
def run(self) -> str:
pass
#第二层产品
class ConcreteProduct1(Product):
def run(self) -> str:
return "ConcreteProduct1:run()"
#第二层产品
class ConcreteProduct2(Product):
def run(self) -> str:
return "ConcreteProduct2:run()"
#客户代码
def client_code(f: Factory) -> None:
a = f.create() #第二层的工厂才能create
a.run()
print(f.exec())
def main():
client_code(ConcreteFactory1())
print("\n")
client_code(ConcreteFactory2())
if __name__ == "__main__":
main()
\;\\\;\\\;
3建造者
1,产品可以分为不同部分;
- 抽象工厂是一个产品一个类,建造者是多个产品一个类
2,构建与显示分开;
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any
#第一层建造者
class Builder(ABC):
@property
@abstractmethod
def product(self) -> None:
pass
@abstractmethod
def produce_part_a(self) -> None:
pass
@abstractmethod
def produce_part_b(self) -> None:
pass
@abstractmethod
def produce_part_c(self) -> None:
pass
#第二层建造者
class ConcreteBuilder1(Builder):
def __init__(self) -> None:
self.reset()
def reset(self) -> None:
self._product = Product1()
@property #让函数可以像属性一样被访问
def product(self) -> Product1:
old_p = self._product #保存旧值
self.reset() #生成一个新值
return old_p #返回旧值
#建造各部分,就是把产品添加到产品的列表中
def produce_part_a(self) -> None:
self._product.add("PartA1")
def produce_part_b(self) -> None:
self._product.add("PartB1")
def produce_part_c(self) -> None:
self._product.add("PartC1")
#第一层产品
class Product1():
def __init__(self) -> None:
self.parts = []
def add(self, part: Any) -> None:
self.parts.append(part)
def show(self) -> None:
print(f"Product parts: {', '.join(self.parts)}", end="")
#管理者
class Manager:
def __init__(self) -> None:
self._builder = None
@property #获取属性builder
def builder(self) -> Builder:
return self._builder
@builder.setter #设置属性builder。有了获取和设置,可以直接使用builder当属性(封装了一下)
def builder(self, builder: Builder) -> None:
self._builder = builder
def build_minimal_viable_product(self) -> None:
self.builder.produce_part_a()
def build_full_featured_product(self) -> None:
self.builder.produce_part_a()
self.builder.produce_part_b()
self.builder.produce_part_c()
def Main():
m = Manager()
builder = ConcreteBuilder1()
m.builder = builder
print("Standard basic product: ")
m.build_minimal_viable_product() #只建造基础款产品
builder.product.show()
print("\n")
print("Standard full featured product: ")
m.build_full_featured_product() #建造完整版产品
builder.product.show()
print("\n")
print("Custom product: ")
builder.produce_part_a()
builder.produce_part_b()
builder.product.show()
if __name__ == "__main__":
Main()
\;\\\;\\\;
4原形
原形是每一个实体,当中都有一个parent指向上一个,所以原形就是一个个连在一起和链表一样。
可以用在拷贝已有实例,
import copy
# 自引用实体类
class Entity:
def __init__(self):
self.parent = None
def set_parent(self, parent): #连接上一级
self.parent = parent
# 组件类
class Component:
def __init__(self, number, items, ref):
self.items = items #一个包含多种类型对象的列表
self.number = number
self.ref = ref #引用的实体
def __copy__(self):
# 浅拷贝
items = copy.copy(self.items)
ref = copy.copy(self.ref)
new = self.__class__(items, self.number, ref)
new.__dict__.update(self.__dict__)
return new
def __deepcopy__(self, memo=None):
# 深拷贝
if memo is None:
memo = {}
items = copy.deepcopy(self.items, memo)
ref = copy.deepcopy(self.ref, memo)
new = self.__class__(items, self.number, ref)
new.__dict__ = copy.deepcopy(self.__dict__, memo)
return new
def main():
# 创建一个包含多种类型对象的列表
items = [1, {1, 2, 3}, [1, 2, 3]]
# 创建一个自引用实体
ref = Entity()
# 创建一个组件实例
component = Component(23, items, ref)
# 设置自引用实体的父对象
ref.set_parent(component)
# 浅拷贝组件
shallow_copied = copy.copy(component)
# 修改浅拷贝组件的列表
shallow_copied.items.append("another object")
# 检查原始组件的列表是否受到影响
if component.items[-1] == "another object":
print("修改浅拷贝组件的列表,原始组件的列表也受到影响。")
else:
print("修改浅拷贝组件的列表,原始组件的列表不受影响。")
# 修改原始组件的列表中的集合
component.items[1].add(4)
if 4 in shallow_copied.items[1]:
print("修改原始组件的集合,浅拷贝组件的集合也受到影响。")
else:
print("修改原始组件的集合,浅拷贝组件的集合不受影响。")
# 深拷贝组件
deep_copied = copy.deepcopy(component)
# 修改深拷贝组件的列表
deep_copied.items.append("one more object")
if component.items[-1] == "one more object":
print("修改深拷贝组件的列表,原始组件的列表也受到影响。")
else:
print("修改深拷贝组件的列表,原始组件的列表不受影响。")
# 修改原始组件的列表中的集合
component.items[1].add(10)
if 10 in deep_copied.items[1]:
print("修改原始组件的集合,深拷贝组件的集合也受到影响。")
else:
print("修改原始组件的集合,深拷贝组件的集合不受影响。")
# 检查深拷贝对象的自引用实体的父对象
print(f"id(deep_copied.ref.parent): {id(deep_copied.ref.parent)}")
print(f"id(deep_copied.ref.parent.ref.parent): {id(deep_copied.ref.parent.ref.parent)}")
print("这表明深拷贝对象包含相同的引用,不会重复克隆。")
if __name__ == "__main__":
main()
\;\\\;\\\;
5单例
确保该类只有一个实例
#单例的meta类
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
#设置meta类
class Singleton(metaclass=SingletonMeta):
def some_business_logic(self):
print('do something.')
def Main():
s1 = Singleton()
s2 = Singleton()
if id(s1) == id(s2):
print("Singleton works, both variables contain the same instance.")
else:
print("Singleton failed, variables contain different instances.")
if __name__ == "__main__":
Main()
\;\\\;\\\;
6适配器
接口转换,把specific_request()转换成request()
表面上使用目标的request(),实际上使用被适配者的specific_request()
# 目标类,定义客户端期望的接口
class Target:
def request(self) -> str:
return "Target:request"
# 被适配者类,具有不兼容的接口
class Adaptee:
def specific_request(self) -> str:
return "Adaptee:specific_request"
# 适配器类,将被适配者接口转换为目标接口
class Adapter(Target, Adaptee):
def request(self) -> str: #使用的是Target接口,内部实际上用的被适配者的接口
return f"Adapter:request -> {self.specific_request()[::-1]}"
# 客户端代码
def client_code(t: Target) -> None:
print(t.request())
def main():
#目标这么写
print("Client: I can work just fine with the Target objects:")
t = Target()
client_code(t)
print()
#被失陪者这么写
a = Adaptee()
print("Client: The Adaptee class has a weird interface. See, I don't understand it:")
print(f"Adaptee: {a.specific_request()}")
print()
#调用适配器,实际上内部还是调用被适配者的函数
print("Client: But I can work with it via the Adapter:")
adapter = Adapter()
client_code(adapter)
if __name__ == "__main__":
main()
\;\\\;\\\;
7桥接
桥接模式将人员和实现给分离开
适配器只是一个类对类的封装
from __future__ import annotations
from abc import ABC, abstractmethod
#第一层人
class People:
def __init__(self, implementation: Implementation) -> None:
self.implementation = implementation
def say(self) -> str:
return f"People:say -> {self.implementation.run()}"
#第二层人
class NPC(People):
def say(self) -> str:
return f"NPC:say -> {self.implementation.run()}"
#第一层实现
class Implementation(ABC):
@abstractmethod
def run(self) -> str:
pass
#第二层实现
class ConcreteA(Implementation):
def run(self) -> str:
return "ConcretenA: Here's the result on the platform A."
#第二层实现
class ConcreteB(Implementation):
def run(self) -> str:
return "ConcreteB: Here's the result on the platform B."
#客户代码
def client_code(p: People) -> None:
print(p.say(), end="")
def Main():
w = ConcreteA() #创建第二层实现
p = People(w) #传给第一层人来调用
client_code(p)
print("\n")
w = ConcreteB() #创建第二层实现
p = NPC(w) #传给第二层人来调用
client_code(p)
if __name__ == "__main__":
Main()
\;\\\;\\\;
8组合
都说不要objective面向对象,要面向组合Composition。但是这里的组合模式不一样,指的是同一棵树中类元素的组合,也就是将类实例添加到容器中。
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import List
#第一层组件
class Component(ABC):
@property
def parent(self) -> Component:
return self._parent
@parent.setter
def parent(self, parent: Component):
self._parent = parent
def add(self, component: Component) -> None:
pass
def remove(self, component: Component) -> None:
pass
def is_composite(self) -> bool:
return False
@abstractmethod
def operation(self) -> str:
pass
#第二层组件
class Leaf(Component):
def operation(self) -> str:
return "Leaf"
#第二层组件
class Composite(Component):
def __init__(self) -> None:
self._children: List[Component] = []
def add(self, c: Component) -> None:
self._children.append(c)
c.parent = self
def remove(self, c: Component) -> None:
self._children.remove(c)
c.parent = None
def is_composite(self) -> bool:
return True
def operation(self) -> str:
results = []
for child in self._children:
results.append(child.operation())
return f"Branch({'+'.join(results)})"
#客户代码
def client_code(c: Component) -> None:
print(f"RESULT: {c.operation()}", end="")
#客户代码
def client_code2(c1: Component, c2: Component) -> None:
if c1.is_composite():
c1.add(c2) #多加一个叶子
print(f"RESULT: {c1.operation()}", end="")
def Main():
simple = Leaf()
print("Client: I've got a simple component:")
client_code(simple)
print("\n")
#创建根节点
tree = Composite()
#分支下面加两个叶子
branch1 = Composite()
branch1.add(Leaf())
branch1.add(Leaf())
#另一个分支下面加一个叶子
branch2 = Composite()
branch2.add(Leaf())
#两个分支都作为根结点的叶子
tree.add(branch1)
tree.add(branch2)
print("Client: Now I've got a composite tree:")
client_code(tree)
print("\n")
print("Client: I don't need to check the components classes even when managing the tree:")
client_code2(tree, simple)
if __name__ == "__main__":
Main()
\;\\\;\\\;
9装饰器
就是在执行exec()函数前,添加一层或多层其他函数的执行
#第一层组件
class Component():
def exec(self) -> str:
pass
#第二层组件
class ConcreteComponent(Component):
def exec(self) -> str:
return "ConcreteComponent"
#第一层装饰器 / 第二层组件
class Decorator(Component):
_component: Component = None
def __init__(self, c: Component) -> None:
self._component = c
@property #能外部获取component属性
def component(self) -> Component:
return self._component
def exec(self) -> str:
return self._component.exec()
#第二层装饰器 / 第三层组件
class ConcreteA(Decorator):
def exec(self) -> str:
return f"ConcreteA -> {self.component.exec()}"
#第二层装饰器 / 第三层组件
class ConcreteB(Decorator):
def exec(self) -> str:
return f"ConcreteB -> {self.component.exec()}"
#客户代码
def client_code(c: Component) -> None:
print(f"RESULT: {c.exec()}", end="")
def Main():
simple = ConcreteComponent()
print("Client: I've got a simple component:")
client_code(simple) #没装饰直接使用
print("\n")
decorator1 = ConcreteA(simple) #前面用装饰类先执行一下
decorator2 = ConcreteB(decorator1) #前面用装饰类先执行一下
print("Client: Now I've got a decorated component:")
client_code(decorator2) #嵌套装饰了两层后调用
if __name__ == "__main__":
Main()
\;\\\;\\\;
感觉不如python的装饰器,不用写成复杂的类也能装饰,如下。
并不一定要每个设计模式都懂,也不是一定要用设计模式。用的时候类多了,自然就形成复杂的调用关系了。
import time
#这个装饰器起到计时的作用
def time_it(func):
#包裹住
def wrapper(*args, **kwargs):
start_time = time.time()
#执行被装饰的函数
result = func(*args, **kwargs)
end_time = time.time()
print(f"Function {func.__name__} took {end_time - start_time:.6f} seconds to execute")
return result
return wrapper
@time_it
def compute_sum(n):
return sum(range(n))
def Main():
compute_sum(1000000)
if __name__ == "__main__":
Main()
\;\\\;\\\;
10门面
为了隐藏子系统,所以用一个外观类(门面类)封装一下
from __future__ import annotations
#门面
class Facade:
def __init__(self, subsystem1: Subsystem1, subsystem2: Subsystem2) -> None:
self._subsystem1 = subsystem1 or Subsystem1()
self._subsystem2 = subsystem2 or Subsystem2()
def operation(self) -> str:
results = []
results.append("Facade initializes subsystems:")
results.append(self._subsystem1.operation1())
results.append(self._subsystem2.operation1())
results.append("Facade orders subsystems to perform the action:")
results.append(self._subsystem1.operation_n())
results.append(self._subsystem2.operation_z())
return "\n".join(results)
class Subsystem1:
def operation1(self) -> str:
return "Subsystem1: Ready!"
def operation_n(self) -> str:
return "Subsystem1: Go!"
class Subsystem2:
def operation1(self) -> str:
return "Subsystem2: Get ready!"
def operation_z(self) -> str:
return "Subsystem2: Fire!"
def client_code(facade: Facade) -> None:
print(facade.operation(), end="")
def Main():
subsystem1 = Subsystem1()
subsystem2 = Subsystem2()
facade = Facade(subsystem1, subsystem2)
client_code(facade)
if __name__ == "__main__":
Main()
\;\\\;\\\;
11代理
。。。和装饰器一样。。。绷不住了
from abc import ABC, abstractmethod
#第一层池子
class Pool(ABC):
@abstractmethod
def request(self) -> None:
pass
#第二层池子
class ConcretePool(Pool):
def request(self) -> None:
print("ConcretePool:request")
class Proxy(Pool):
def __init__(self, rp: ConcretePool) -> None:
self._real_Pool = rp
def request(self) -> None:
if self.check_access():
self._real_Pool.request()
self.log_access()
def check_access(self) -> bool:
print("Proxy:check_access")
return True
def log_access(self) -> None:
print("Proxy:log_access", end="")
def client_code(p: Pool) -> None:
p.request()
def Main():
print("Client: Executing the client code with a real Pool:")
real_Pool = ConcretePool()
client_code(real_Pool)
print("")
print("Client: Executing the same client code with a proxy:")
proxy = Proxy(real_Pool)
client_code(proxy)
if __name__ == "__main__":
Main()
\;\\\;\\\;
12共享
维护一个字典,value是共享类,不同的key对应不同的实例,甚至是同一个实例,这样就节约了空间,达到了共享!
import json
from typing import Dict, List
# 共享类
class Flyweight:
def __init__(self, shared_state: List[str]) -> None:
self._shared_state = shared_state #初始化的时候传进来一个
def exec(self, unique_state: List[str]) -> None:
s = json.dumps(self._shared_state)
u = json.dumps(unique_state) #执行的时候又传进来一个
print(f"Flyweight:exec -> \n\t{s}\n\t{u}", end="")
# 工厂类
class Factory:
#通过字符串key去查找共享类
_flyweights: Dict[str, Flyweight] = {}
def __init__(self, initial_flyweights: List[List[str]]) -> None:
for state in initial_flyweights:
self._flyweights[self.get_key(state)] = Flyweight(state) #添加元素
#每个key都是由多个字符串用下划线连起来组成的
def get_key(self, state: List[str]) -> str:
return "_".join(sorted(state))
def get_flyweight(self, shared_state: List[str]) -> Flyweight:
key = self.get_key(shared_state)
if key not in self._flyweights: #如果没有这个key
print("Factory:get_flyweight -> Can't find a flyweight, creating new one.")
self._flyweights[key] = Flyweight(shared_state)
else:
print("Factory:get_flyweight -> Reusing existing flyweight.")
return self._flyweights[key]
def show(self) -> None:
count = len(self._flyweights)
print(f"Factory: I have {count} flyweights:")
print("\n".join(self._flyweights.keys()), end="")
# 一个新业务
def add_car_to_police_database(
factory: Factory, #工厂
plates: str, #传入工厂的形参
owner: str, #传入工厂的形参
brand: str, #传入工厂的形参
model: str, #传入工厂的形参
color: str #传入工厂的形参
) -> None:
# print("\nClient: Adding a car to database.")
flyweight = factory.get_flyweight([brand, model, color])
flyweight.exec([plates, owner])
def main():
factory = Factory([
["Chevrolet", "Camaro2018", "pink"],
["Mercedes Benz", "C300", "black"],
["Mercedes Benz", "C500", "red"],
["BMW", "M5", "red"],
["BMW", "X6", "white"],
])
factory.show()
print("\n")
#增加一条信息
add_car_to_police_database(factory, "CL234IR", "James Doe", "BMW", "M5", "red")
print("\n")
# 增加一条信息
add_car_to_police_database(factory, "CL234IR", "James Doe", "BMW", "X1", "red")
print("\n")
factory.show()
if __name__ == "__main__":
main()
\;\\\;\\\;
复杂的设计模式
下篇继续
\;\\\;\\\;