设计模式
简单工厂模式
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
class AliPay(Payment):
def pay(self, money):
print(f"支付宝支付 {money} 元")
class WechatPay(Payment):
def pay(self, money):
print(f"微信支付 {money} 元")
class PaymentFactory:
def create_payment(self, method):
if method == "AliPay":
return AliPay()
elif method == "wechat":
return WechatPay()
else:
raise TypeError(f"No such payment named {method}")
factory = PaymentFactory()
payment = factory.create_payment("AliPay")
payment.pay(1000)
工厂方法模式
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
class AliPay(Payment):
def pay(self, money):
print(f"支付宝支付 {money} 元")
class WechatPay(Payment):
def pay(self, money):
print(f"微信支付 {money} 元")
class PaymentFactory(metaclass=ABCMeta):
@abstractmethod
def create_payment(self):
pass
class AliPayFactory(PaymentFactory):
def create_payment(self):
return AliPay()
class WechatFactory(PaymentFactory):
def create_payment(self):
return WechatPay()
factory = AliPayFactory()
pay = factory.create_payment()
pay.pay(1000)
factory = WechatFactory()
pay = factory.create_payment()
pay.pay(1000)
抽象工厂模式
from abc import ABCMeta, abstractmethod
# ======= 抽象产品 =======
class PhoneShell(metaclass=ABCMeta):
@abstractmethod
def show_shell(self):
pass
class CPU(metaclass=ABCMeta):
@abstractmethod
def show_cpu(self):
pass
class OS(metaclass=ABCMeta):
@abstractmethod
def show_os(self):
pass
# ======= 抽象工厂 =======
class PhoneFactory(metaclass=ABCMeta):
@abstractmethod
def make_shell(self):
pass
@abstractmethod
def make_cpu(self):
pass
@abstractmethod
def make_os(self):
pass
# ======= 具体产品 =======
class SmallShell(PhoneShell):
def show_shell(self):
print("普通手机小手机壳")
class BigShell(PhoneShell):
def show_shell(self):
print("普通手机大手机壳")
class AppleShell(PhoneShell):
def show_shell(self):
print("苹果手机壳")
class SnapDragonCPU(CPU):
def show_cpu(self):
print("骁龙CPU")
class MediaTekCPU(CPU):
def show_cpu(self):
print("联发科CPU")
class AppleCPU(CPU):
def show_cpu(self):
print("苹果CPU")
class AndroidOS(OS):
def show_os(self):
print("安卓OS")
class AppleOS(OS):
def show_os(self):
print("苹果OS")
# ======= 具体工厂 =======
class MiFactory(PhoneFactory):
def make_shell(self):
return BigShell()
def make_cpu(self):
return SnapDragonCPU()
def make_os(self):
return AndroidOS()
# 限制组件搭配,不允许随意组装
class iPhoneFactory(PhoneFactory):
def make_shell(self):
return AppleShell()
def make_cpu(self):
return AppleCPU()
def make_os(self):
return AppleOS()
# ======= 客户端 =======
class Phone:
def __init__(self, shell: PhoneShell, cpu: CPU, os: OS):
self.shell = shell
self.cpu = cpu
self.os = os
def show_info(self):
print("手机信息:")
self.shell.show_shell()
self.cpu.show_cpu()
self.os.show_os()
def make_phone(factory: PhoneFactory):
shell = factory.make_shell()
cpu = factory.make_cpu()
os = factory.make_os()
return Phone(shell, cpu, os)
mi_phone = make_phone(MiFactory())
mi_phone.show_info()
iphone = make_phone(iPhoneFactory())
iphone.show_info()
建造者模式
from abc import ABCMeta, abstractmethod
class Player:
def __init__(self, face=None, body=None, arm=None, leg=None):
self.face = face
self.body = body
self.arm = arm
self.leg = leg
def __str__(self):
return f"{self.face} {self.body} {self.arm} {self.leg}"
class PlayerBuilder(metaclass=ABCMeta):
@abstractmethod
def build_face(self):
pass
@abstractmethod
def build_body(self):
pass
@abstractmethod
def build_arm(self):
pass
@abstractmethod
def build_leg(self):
pass
class SexyGirlBuilder(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = "漂亮脸蛋"
def build_body(self):
self.player.body = "苗条"
def build_arm(self):
self.player.arm = "修长手臂"
def build_leg(self):
self.player.leg = "大长腿"
class MonsterBuilder(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = "怪兽脸"
def build_body(self):
self.player.body = "怪兽身材"
def build_arm(self):
self.player.arm = "长毛的胳膊"
def build_leg(self):
self.player.leg = "长毛的腿"
class PlayerDirector:
# 控制游戏角色组装顺序(比如先要有躯干,才能设置其他四肢)
def build_player(self, builder):
builder.build_body()
builder.build_face()
builder.build_arm()
builder.build_leg()
return builder.player
sexy_girl = SexyGirlBuilder()
director = PlayerDirector()
persion = director.build_player(sexy_girl)
print(persion)
monster = MonsterBuilder()
director = PlayerDirector()
persion = director.build_player(monster)
print(persion)
单例模式
class Singleton:
def __new__(cls, *args, **kwargs):
if not hasattr(cls, "_instance"):
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
class MyClass(Singleton):
def __init__(self, a):
self.a = a
a = MyClass(10)
b = MyClass(20)
print(a.a) # 20
print(b.a) # 20
print(id(a), id(b)) # id(a) = id(b)
适配器模式
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
class AliPay(Payment):
def pay(self, money):
print(f"支付宝支付 {money} 元")
class WechatPay(Payment):
def pay(self, money):
print(f"微信支付 {money} 元")
# Note: 银联支付用的是 cost 其他支付用的是 pay, 需要用到下面的适配器模式进行转换
class BankPay:
def cost(self, money):
print(f"银联支付 {money} 元")
# 类适配器
class NewBankPay(Payment, BankPay):
def pay(self, money):
self.cost(money)
# 对象适配器
class PaymentAdapter(Payment):
def __init__(self, payment):
self.payment = payment
def pay(self, money):
return self.payment.cost(money)
pay = AliPay()
pay.pay(1000)
pay = NewBankPay()
pay.pay(1000)
pay = PaymentAdapter(NewBankPay())
pay.pay(1000)
桥模式
from abc import ABCMeta, abstractmethod
class Shape(metaclass=ABCMeta):
# 把颜色和形状做关联,将颜色作为形状的一个属性
def __init__(self, color):
self.color = color
@abstractmethod
def draw(self):
pass
class Color(metaclass=ABCMeta):
@abstractmethod
def paint(self, shape):
pass
class Rectangle(Shape):
name = "长方形"
def draw(self):
# draw rectangle logic
self.color.paint(self)
class Circle(Shape):
name = "圆形"
def draw(self):
# draw circle logic
self.color.paint(self)
class Red(Color):
def paint(self, shape):
print(f"红色的{shape.name}")
class Blue(Color):
def paint(self, shape):
print(f"蓝色的{shape.name}")
shape = Rectangle(Red())
shape.draw()
shape = Rectangle(Blue())
shape.draw()
shape = Circle(Red())
shape.draw()
组合模式
from abc import ABCMeta, abstractmethod
# 抽象组件
class Graphic(metaclass=ABCMeta):
@abstractmethod
def draw(self):
pass
# 叶子组件
class Point(Graphic):
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"点 ({self.x}, {self.y})"
def draw(self):
print(str(self))
# 叶子组件
class Line(Graphic):
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
def __str__(self):
return f"线段 ({self.p1}, {self.p2})"
def draw(self):
print(str(self))
# 复合组件(包含多个叶子组件)
class Picture(Graphic):
def __init__(self, iterable):
self.children = []
for g in iterable:
self.add(g)
def add(self, graphic):
self.children.append(graphic)
def draw(self):
print("----复合图形----")
for g in self.children:
g.draw()
print("----复合图形----")
line = Line(Point(1, 1), Point(2, 2))
print(line)
point1 = Point(2, 3)
line1 = Line(Point(3, 4), Point(6, 7))
line2 = Line(Point(1, 5), Point(2, 8))
pic1 = Picture([point1, line1, line2])
point2 = Point(4, 4)
line3 = Line(Point(1, 1), Point(0, 0))
pic2 = Picture([point2, line3])
pic = Picture([pic1, pic2])
pic.draw()
外观模式
# 子系统类
class CPU:
def run(self):
print("CPU开始运行")
def stop(self):
print("CPU停止运行")
# 子系统类
class Disk:
def run(self):
print("硬盘开始工作")
def stop(self):
print("硬盘停止工作")
# 子系统类
class Memory:
def run(self):
print("内存开始运行")
def stop(self):
print("内存停止运行")
# 外观类
class Computer:
def __init__(self):
self.cpu = CPU()
self.disk = Disk()
self.memory = Memory()
def run(self):
self.cpu.run()
self.disk.run()
self.memory.run()
def stop(self):
self.cpu.stop()
self.disk.stop()
self.memory.stop()
computer = Computer()
computer.run()
computer.stop()
代理模式
from abc import ABCMeta, abstractmethod
# 抽象实体
class Subject(metaclass=ABCMeta):
@abstractmethod
def get_content(self):
pass
@abstractmethod
def set_content(self, content):
pass
# 实体
class RealSubject(Subject):
def __init__(self, filename):
self.filename = filename
print("读取文件内容")
with open(filename, "r") as f:
self.content = f.read()
def get_content(self):
return self.content
def set_content(self, content):
with open(self.filename, "w") as f:
f.write(content)
# 虚代理
class VirtualProxy(Subject):
def __init__(self, filename):
self.filename = filename
self.subject = None # 初始化时设置为空,仅当调用 get_content 时才去调用真实的 get_content 方法
def get_content(self):
if not self.subject:
self.subject = RealSubject(self.filename)
return self.subject.get_content()
def set_content(self, content):
if not self.subject:
self.subject = RealSubject(self.filename)
return self.subject.set_content(content)
# 保护代理
class ProtectedProxy(Subject):
def __init__(self, filename):
self.subject = RealSubject(filename)
def get_content(self):
return self.subject.get_content()
def set_content(self, content):
# 验证权限相关逻辑 ...
raise PermissionError("无写入权限")
# NOTE: 在使用虚代理前,构造RealSubject时(此时还未调用get_content())已经加载具体的文件了
subject = RealSubject("/mnt/d/src/python/TestBase/tmp/test.txt")
subject.get_content()
# NOTE: 在使用虚代理后,构造RealSubject时不会加载具体的文件,仅在调用 get_content 时才加哉文件
subject = VirtualProxy("/mnt/d/src/python/TestBase/tmp/test.txt")
print(subject.get_content())
# NOTE: 在使用保护代理后,仅有读权限,无写权限
subject = ProtectedProxy("/mnt/d/src/python/TestBase/tmp/test.txt")
print(subject.get_content())
subject.set_content("abc") # PermissionError: 无写入权限
责任链模式
from abc import ABCMeta, abstractmethod
# 抽象处理者
class Handler(metaclass=ABCMeta):
@abstractmethod
def handle_leave(self, day):
pass
# 具体处理者
class GeneralManager(Handler):
def handle_leave(self, day):
if day < 10:
print(f"总经理准假 {day} 天")
else:
print("不符合公司规定, 不予批准")
# 具体处理者
class ProjectManager(Handler):
def __init__(self):
self.next = GeneralManager()
def handle_leave(self, day):
if day <= 5:
print(f"项目经理准假 {day} 天")
else:
print("项目经理权限不足")
self.next.handle_leave(day)
# 具体处理者
class TeamLeader(Handler):
def __init__(self):
self.next = ProjectManager()
def handle_leave(self, day):
if day <= 3:
print(f"总经理准假 {day} 天")
else:
print("Team Leader 权限不足")
self.next.handle_leave(day)
# 责任链:Team Leader -> Project Manager -> General Manager
handle = TeamLeader()
handle.handle_leave(1)
handle.handle_leave(5)
handle.handle_leave(7)
handle.handle_leave(11)
观察者模式
from abc import ABCMeta, abstractmethod
# 抽象订阅者
class Observer(metaclass=ABCMeta):
@abstractmethod
def update(self, publisher): # publisher 是一个 Publisher 类的对象
pass
# 抽象发布者
class Publisher:
def __init__(self):
self.observers = []
def attach(self, observer):
self.observers.append(observer)
def detach(self, observer):
self.observers.remove(observer)
def notify(self):
for observer in self.observers:
observer.update(self)
# 具体发布者
class StaffPublisher(Publisher):
def __init__(self, company_info=None):
super().__init__()
self.__company_info = company_info
@property
def company_info(self):
return self.__company_info
@company_info.setter
def company_info(self, info):
self.__company_info = info
self.notify()
class Staff(Observer):
def __init__(self):
self.company_info = None
def update(self, publisher):
self.company_info = publisher.company_info
publisher = StaffPublisher("初始化公司信息")
staff01 = Staff()
staff02 = Staff()
publisher.attach(staff01)
publisher.attach(staff02)
publisher.company_info = "公司今年业绩非常好,给大家发奖金"
print(staff01.company_info)
print(staff02.company_info)
publisher.detach(staff01)
publisher.company_info = "公司明天放假"
print(staff01.company_info)
print(staff02.company_info)
策略模式
from abc import ABCMeta, abstractmethod
class Strategy(metaclass=ABCMeta):
@abstractmethod
def execute(self, data):
pass
class FastStrategy(Strategy):
def execute(self, data):
print(f"用较快的策略处理 {data}")
class SlowStrategy(Strategy):
def execute(self, data):
print(f"用较慢的策略处理 {data}")
class Context:
def __init__(self, strategy, data):
self.data = data
self.strategy = strategy
def set_strategy(self, strategy):
self.strategy = strategy
def do_strategy(self):
self.strategy.execute(self.data)
data = "[...]"
s1 = FastStrategy()
s2 = SlowStrategy()
context = Context(s1, data)
context.do_strategy()
context = Context(s2, data)
context.do_strategy()
模板方法模式
from time import sleep
from abc import ABCMeta, abstractmethod
class Window(metaclass=ABCMeta):
@abstractmethod
def start(self):
pass
@abstractmethod
def repaint(self):
pass
@abstractmethod
def stop(self):
pass
# 模板方法
def run(self):
self.start()
while True:
try:
self.repaint()
sleep(1)
except KeyboardInterrupt:
break
self.stop()
class MyWindow(Window):
def __init__(self, msg):
self.msg = msg
def start(self):
print("窗口开始运行")
def stop(self):
print("窗口结束运行")
def repaint(self):
print(self.msg)
window = MyWindow("hello...")
window.run()
学习资源