设计模式:对设计软件中普遍存在(反复出现)的各种问题,所提出的解决方案。每一个设计模式系统的命名、解释和评价了面向对象系统中一个重要的和重要出现的设计。
封装
继承
多态
接口:若干抽象方法的集合。
作用:限制实现接口的类必须按照接口给定的调用方法实现这些方法;对高层模块隐藏了类的内部实现。
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money):
pass
class WechatPay(Payment):
def pay(self,money):
pass
print("微信支付了%d元"%money)
class AliPay(Payment):
def pay(self,money):
print("支付宝支付了%d元"%money)
w = WechatPay()
w.pay(100)
a = AliPay()
a.pay(200)
开发封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
里氏替换原则:所有引用父类的地方必须能透明地使用其子类的对象。
依赖倒置原则:高层模块不应该依赖底层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程。
接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
from abc import ABCMeta,abstractmethod
class LandAnimal(metaclass=ABCMeta):
@abstractmethod
def walk(self):
pass
class AquatilicAnimal(metaclass=ABCMeta):
@abstractmethod
def swim(self):
pass
class BirdsAnimal(metaclass=ABCMeta):
@abstractmethod
def fly(self):
pass
class Tiger(LandAnimal):
def walk(self):
print("tiger is runing!!!")
class Frog(AquatiliCAnimal):
def swim(self):
print("frog is swimming!!!")
class Swallow(BirdsAnimal):
def fly(self):
print("swallows are flying in the blue sky!!!")
t = Tiger()
t.walk()
f = Frog()
f.swim()
s = Swallow()
s.fly()
单一职责原则:不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money):
pass
class WechatPay(Payment):
def pay(self,money):
pass
print("微信支付了%d元"%money)
class AliPay(Payment):
def __init__(self,use_huabei=False):
self.use_huabei = use_huabei
def pay(self,money):
if self.use_huabei:
print("花呗支付了%d元"%money)
else:
print("余额宝支付了%d元"%money)
class PaymentFatory:
def create_payment(self,method):
if method == 'alipay':
return AliPay()
elif method == 'huabei':
return AliPay(use_huabei=True)
elif method == "wechat":
return WechatPay()
else:
raise TypeError("No such payment named %s"%method)
# client
pf = PaymentFatory()
p = pf.create_payment('alipay')
p.pay(1000)
优点:
缺点:
# 抽象工厂
class PaymentFactory(metaclass=ABCMeta):
"""工厂类的接口"""
@abstractmethod
def create_payment(self):
pass
# 具体工厂
class AliPayFactory(PaymentFactory):
"""阿里支付工厂"""
def create_payment(self):
return AliPay()
class WechatPayFactory(PaymentFactory):
"""微信支付工厂"""
def create_payment(self):
return WechatPay()
class HuaBeiFactory(PaymentFactory):
"""花呗支付工厂"""
def create_payment(self):
return AliPay(use_hb=True)
class BankPayFactory(PaymentFactory):
"""银联支付工厂"""
def create_payment(self):
return BankPay()
# 抽象产品
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
# 具体产品
class WechatPay(Payment):
def pay(self, money):
print(f"微信支付了{money}元")
class BankPay(Payment):
def pay(self, money):
print(f"银行卡支付了{money}元")
class AliPay(Payment):
def __init__(self, use_hb=False):
self.use_hb = use_hb
def pay(self, money):
if self.use_hb:
print(f"花呗支付了{money}元")
else:
print(f"余额宝支付了{money}元")
# client
pf = HuaBeiFactory()
p = pf.create_payment()
p.pay(1000)
pf1 = BankPayFatory()
p1 = pf1.create_payment()
p1.pay(2000)
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 MediaCPU(CPU):
def show_cpu(self):
print("联发科CPU")
class AppleCPU(CPU):
def show_cpu(self):
print("苹果CPU")
class Android(OS):
def show_os(self):
print("Android系统")
class IOS(OS):
def show_os(self):
print("IOS系统")
# 具体工厂
class MiFactory(PhoneFactory):
def make_cpu(self):
return SnapDragonCPU()
def make_os(self):
return Android()
def make_shell(self):
return BigShell()
class HuaweiFactory(PhoneFactory):
def make_cpu(self):
return SnapDragonCPU()
def make_os(self):
return Android()
def make_shell(self):
return SmallShell()
class IphoneFactory(PhoneFactory):
def make_cpu(self):
return AppleCPU()
def make_os(self):
return IOS()
def make_shell(self):
return AppleShell()
# 客户端
class Phone:
def __init__(self,cpu,os,shell):
self.cpu = cpu
self.os = os
self.shell = shell
def show_info(self):
print("手机信息:")
self.cpu.show_cpu()
self.os.show_os()
self.shell.show_shell()
def make_phone(factory):
cpu = factory.make_cpu()
os = factory.make_os()
shell = factory.make_shell()
return Phone(cpu,os,shell)
print("====================小米手机====================")
p1 = make_phone(MiFactory())
p1.show_info()
print("====================华为手机====================")
p2 = make_phone(HuaweiFactory())
p2.show_info()
print("====================苹果手机====================")
p3 = make_phone(IphoneFactory())
p3.show_info()
角色:
优点:
缺点:
from abc import ABCMeta,abstractmethod
# 产品
class Player:
def __init__(self,body=None,arm=None,leg=None,face=None):
self.body = body
self.arm = arm
self.leg = leg
self.face = face
def __str__(self):
return "{0},{1},{2},{3}".format(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_leg(self):
pass
@abstractmethod
def build_arm(self):
pass
# 具体建造者
class SexGirlBuilder(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = "漂亮脸蛋"
def build_body(self):
self.player.body = "苗条身材"
def build_leg(self):
self.player.leg = "大长腿"
def build_arm(self):
self.player.arm = "修长胳膊"
class Monster(PlayerBuilder):
def __init__(self):
self.player = Player()
def build_face(self):
self.player.face = "丑八怪"
def build_body(self):
self.player.body = "魁梧大汉"
def build_leg(self):
self.player.leg = "满腿毛"
def build_arm(self):
self.player.arm = "巨猿臂"
# 指挥者(控制组装顺序)
class PlayerDirector:
def build_player(self,builder):
builder.build_body()
builder.build_face()
builder.build_arm()
builder.build_leg()
return builder.player
# client
builder = SexGirlBuilder()
director = PlayerDirector()
p = director.build_player(builder)
print(p)
# 单例模式
class Singleton:
def __new__(cls,*args,**kwargs):
if not hasattr(cls,"_instance"):
cls._instance = super().__new__(cls)
return cls._instance
class Myclass(Singleton):
def __init__(self,num):
self.num = num
a = Myclass(10)
b = Myclass(20)
print(a.num)
print(b.num)
print(id(a))
print(id(b))
# 单例模式
class Mysingleton:
__obj = None
__init_flag = True
def __new__(cls,*args,**kwargs):
if cls.__obj == None:
cls.__obj = super().__new__(cls)
return cls.__obj
def __init__(self,name):
if Mysingleton.__init_flag:
print("init....")
self.name = name
Mysingleton.__init_flag = False
a = Mysingleton('aa')
print(a)
b = Mysingleton('bb')
print(b)
print(id(a))
print(id(b))
# 混合模式(单例+工厂)
class CarFactory:
"""工厂只需要一个"""
__obj = None
__init_flag = True
def __new__(cls,*args,**kwargs):
if cls.__obj == None:
cls.__obj = super().__new__(cls)
return cls.__obj
def __init__(self):
if CarFactory.__init_flag:
print('init....')
CarFactory.__init_flag = False
def createCar(self,brand):
if brand == "奔驰":
return Benz()
elif brand == "宝马":
return BMW()
elif brand == "比亚迪":
return BYD()
else:
return "未知品牌,不能创建"
class Benz:
pass
class BMW:
pass
class BYD:
pass
f = CarFactory()
c1 = f.createCar("奔驰")
c2 = f.createCar("宝马")
print(c1)
print(c2)
f1 = CarFactory()
print('f:',f,id(f))
print('f1:',f1,id(f1))
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self,money):
pass
class WechatPay(Payment):
def pay(self,money):
pass
print("微信支付了%d元"%money)
class AliPay(Payment):
def pay(self,money):
print("支付宝支付了%d元"%money)
class BankPay:
def cost(self,money):
print("银联支付%d元"%money)
class ApplekPay:
def cost(self,money):
print("苹果支付%d元"%money)
# 类适配器
# class NewBankPay(Payment, BankPay):
# def pay(self,money):
# self.cost(money)
# p = NewBankPay()
# p.pay(2000)
# 对象适配器
# 实现接口统一(继承Payment),代码复用(组合(利用类的属性))
class PaymentAdapter(Payment):
def __init__(self,payment):
self.payment = payment
def pay(self,money):
self.payment.cost(money)
p = PaymentAdapter(ApplekPay())
p.pay(2500)
# 组合(在一个类中放入另一个类的对象,代码复用)
# class A:
# pass
# class B:
# def __init__(self):
# self.a = A()
角色:
适用场景
内容:将一个事物的两个维度分离,使其都可以独立地变化。
角色:
应用场景:
优点:
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):
# 绘制长方形的业务逻辑
self.color.paint(self)
class Circle(Shape):
name = "圆形"
def draw(self):
# 绘制圆形的业务逻辑
self.color.paint(self)
class Line(Shape):
name = "直线"
def draw(self):
# 绘制直线的业务逻辑
self.color.paint(self)
class Red(Color):
def paint(self,shape):
print("红色的%s"%shape.name)
class Green(Color):
def paint(self,shape):
print("绿色的%s"%shape.name)
class Blue(Color):
def paint(self,shape):
print("蓝色的%s"%shape.name)
# client
shape = Rectangle(Red())
shape.draw()
shape1 = Circle(Green())
shape1.draw()
shape2 = Line(Blue())
shape2.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 "点坐标(%s,%s)"%(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 "线段[%s,%s]"%(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("============复合图像===========")
# 客户端
p1 = Point(1,3)
l1 = Line(Point(2,2),Point(6,8))
l2 = Line(Point(5,2),Point(8,9))
pic1 = Picture([p1,l1,l2])
# pic1.draw()
p2 = Point(4,3)
l2 = Line(Point(4,2),Point(5,6))
l3 = Line(Point(1,6),Point(2,8))
pic2 = Picture([p2,l2,l3])
# pic2.draw()
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()
# client
c = Computer()
c.run()
c.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("读取文件内容....")
f = open(filename,'r')
self.content = f.read()
print(self.content)
f.close()
def get_content(self):
return self.content
def set_content(self,content):
f = open(self.filename,'w')
f.write(content)
f.close()
class VirtualSubject(Subject):
"""虚代理"""
def __init__(self,filename):
self.filename = filename
self.subj = None
def get_content(self):
if not self.subj:
self.subj = RealSubject(self.filename)
return self.subj.get_content()
def set_content(self,content):
if not self.subj:
self.subj = RealSubject(self.filename)
return self.subj.set_content(content)
class ProjectProxy(Subject):
def __init__(self,filename):
self.subj = RealSubject(filename)
def get_content(self):
return self.subj.get_content()
def set_content(self,content):
# 可以进行身份验证,身份验证不通过抛出权限异常
raise PermissionError("无写入权限!!!")
# subj = RealSubject("test.txt")
# subj = VirtualSubject("test.txt")
# subj.get_content()
# subj.set_content("hello word!!!")
subj1 = ProjectProxy("test.txt")
# subj1.get_content()
subj1.set_content("哈哈,写不进去吧!!!")
from abc import ABCMeta,abstractmethod
# 抽象处理者
class Handle(metaclass=ABCMeta):
@abstractmethod
def handle_leave(self,day):
pass
# 具体处理者
class GeneralManager(Handle):
def handle_leave(self,day):
if day < 15:
print("总经理准假%d天"%day)
else:
print("直接递交辞职报告吧!!!")
class DepartmentManager(Handle):
def __init__(self):
self.next = GeneralManager()
def handle_leave(self,day):
if day <= 5:
print("部门经理准假%d天"%day)
else:
print("超出职权范围内,请假申请转交总经理处理")
self.next.handle_leave(day)
class ProjectDirector(Handle):
def __init__(self):
self.next = DepartmentManager()
def handle_leave(self,day):
if day <= 3:
print("项目经理准假%d天"%day)
else:
print("超出职权范围内,请假申请转交部门经理处理")
self.next.handle_leave(day)
# 客户端
# d = 18
# d = 2
d = 5
h = ProjectDirector()
h.handle_leave(d)
并被自动更新。观察者模式又称“发布-订阅”模式。
角色:
使用场景:
优点:
from abc import ABCMeta,abstractmethod
class Observer(metaclass=ABCMeta):
"""
抽象订阅者
notice:是一个Notice的类
"""
@abstractmethod
def update(self,notice):
pass
# 抽象发布者
class Notice:
def __init__(self):
self.observers = []
def attach(self,obs):
self.observers.append(obs)
def delete_attach(self,obs):
self.observers.remove(obs)
def notify(self):
for obs in self.observers:
obs.update(self)
class StaffNotice(Notice):
"""具体发布者"""
def __init__(self,commpany_info):
super().__init__()
self.__commpany_info = commpany_info
@property
def company_info(self):
return self.__commpany_info
@company_info.setter
def company_info(self,info):
self.__commpany_info = info
self.notify() # 推送
class Staff(Observer):
"""具体订阅者"""
def __init__(self):
self.company_info = None
def update(self,notice):
self.company_info = notice.company_info
# Client
notice = StaffNotice("初始公司信息")
s1 = Staff()
s2 = Staff()
notice.attach(s1)
notice.attach(s2)
notice.company_info = "公司今年业绩非常好,给大家发奖金了!!!"
print(s1.company_info)
print(s2.company_info)
notice.delete_attach(s2)
notice.company_info = "公司从明天起放假3天!!!"
print(s1.company_info)
print(s2.company_info)
内容:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而变化。
角色:
优点:
缺点:
from abc import ABCMeta,abstractmethod
# 抽象策略
class Strategy(metaclass=ABCMeta):
@abstractmethod
def excute(self,data):
pass
# 具体策略
class FastStrategy(Strategy):
def excute(self,data):
print("用较快的策略处理数据%s"%data)
class SlowStrategy(Strategy):
def excute(self,data):
print("用较慢的策略处理数据%s"%data)
# 上下文(封装数据和策略)
class Context:
def __init__(self,strategy,data):
self.strategy = strategy
self.data = data
def set_strategy(self,strategy):
self.strategy = strategy
def do_strategy(self):
self.strategy.excute(self.data)
# Client
data = [1,3,9,100,85,66,77,33,22]
s = SlowStrategy()
s2 = FastStrategy()
c = Context(s,data)
c.do_strategy()
c.set_strategy(s2)
c.do_strategy()
内容:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
角色:
使用场景:
from abc import ABCMeta,abstractmethod
from time import sleep
class Windows(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 MyWindos(Windows):
def __init__(self,msg):
self.msg = msg
def start(self):
print("窗口开启")
def stop(self):
print("窗口关闭")
def repaint(self):
print(self.msg)
# client
MyWindos("hello...").run()