目录
接口
接口:若干抽象方法的集合。
作用:限制实现接口的类必须按照接口给定的调用方法实现这些方法;对高层模块隐藏了类的内部实现。
# 接口的实现
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
class AliPay(Payment):
def __init__(self, huabei=False):
self.huabei = huabei
def pay(self, money):
if self.huabei:
print('花呗支付%s元。' % money)
print('支付宝支付%s元。' % money)
class WechatPay(Payment):
def pay(self, money):
print('微信支付%s元。' % money)
a = WechatPay()
a.pay(100)
面向对象设计SOLID原则
开放封闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展
里氏替换原则:所有引用父类的地方必须能透明地使用其子类对象
依赖倒置原则:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程
接口隔离原则:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些他不需要的接口
单一职责原则:不要存在多余一个导致类变更的原因。通俗讲,即一个类只负责一项职责
设计模式分类
创建型模式(5种)
创建型模式(5种):工厂方法模式,抽象工厂模式,创建者模式,原型模式,单例模式
创建型模式小结:
抽象工厂模式和建造者模式相比于简单工厂模式和工厂方法模式而言更灵活也更复杂。
通常情况下,设计以简单工厂模式或工厂方法模式开始,当你需要更大的灵活性时,则向更复杂的设计模式演化。
简单工厂模式
内容:
不直接向客户端暴露对象创建的实现细节,而是通过工厂类来负责创建产品类的实例。
角色:
工厂角色(creator)
抽象产品角色(product)
具体产品角色(concrete product)
# 简单工厂模式
from abc import ABCMeta, abstractmethod
# 抽象产品
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
# 具体产品
class AliPay(Payment):
def __init__(self, huabei=False):
self.huabei = huabei
def pay(self, money):
if self.huabei:
print('花呗支付%s元。' % money)
print('支付宝支付%s元。' % money)
class WechatPay(Payment):
def pay(self, money):
print('微信支付%s元。' % money)
class NonePayment(Payment):
def pay(self, money):
pass
# 工厂角色
class PayMethods:
def create_payment(self, method):
if method == 'huabei':
return AliPay(True)
elif method == 'zhifubao':
return AliPay()
elif method == 'wechat':
return WechatPay()
else:
print('输入的支付模式不存在')
return NonePayment()
a = PayMethods()
p = a.create_payment('wechat1')
p.pay(100)
优缺点:
优点:隐藏了对象创建的实现细节,客户端不需要修改代码。
缺点:违反了单一职责原则,将创建逻辑集中到一个工厂类里。当添加新产品时,需要修改工厂类代码,违反了开闭原则。
工厂方法模式
内容:
定义一个用来创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。
角色:
抽象工厂角色(creator)
具体工厂角色(concrete creator)
抽象产品角色(product)
具体产品角色(concrete product)
# 工厂方法模式
from abc import ABCMeta, abstractmethod
# 抽象产品
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
# 具体产品
class AliPay(Payment):
def __init__(self, huabei=False):
self.huabei = huabei
def pay(self, money):
if self.huabei:
print('花呗支付%s元。' % money)
else:
print('支付宝支付%s元。' % money)
class WechatPay(Payment):
def pay(self, money):
print('微信支付%s元。' % money)
class NonePayment(Payment):
def pay(self, money):
pass
# 抽象工厂
class PayMentFactory(metaclass=ABCMeta):
@abstractmethod
def create_payment(self):
pass
# 具体工厂
class AlipayFactory(PayMentFactory):
def create_payment(self):
return AliPay()
class HuabeiFactory(PayMentFactory):
def create_payment(self):
return AliPay(True)
class WechatFactory(PayMentFactory):
def create_payment(self):
return AliPay()
a = HuabeiFactory()
p = a.create_payment()
p.pay(100)
优缺点:
优点:每个具体产品都对应一个具体工厂类,不需要修改工厂代码。隐藏了对象创建的实现细节
缺点:每增加一个具体产品类,就必须增加一个相应的具体工厂类
抽象工厂模式
内容:
定义一个工厂类接口,让工厂子类来创建一系列相关或相互依赖的对象。
相比工厂方法模式,抽象工厂模式中的每个具体工厂都生产一套产品。
角色:
抽象工厂角色(creator)
具体工厂角色(concrete creator)
抽象产品角色(product)
具体产品角色(concrete product)
客户端(client)
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 AppleShell(PhoneShell):
def show_shell(self):
print("苹果手机壳")
class AppleCPU(CPU):
def show_cpu(self):
print("苹果CPU")
class AppleOS(OS):
def show_os(self):
print("苹果系统")
class AndroidShell(PhoneShell):
def show_shell(self):
print("安卓手机壳")
class AndroidCPU(CPU):
def show_cpu(self):
print("安卓CPU")
class AndroidOS(OS):
def show_os(self):
print("安卓系统")
# ----------抽象工厂---------
class PhoneFactory(metaclass=ABCMeta):
@abstractmethod
def make_shell(self):
pass
def make_cpu(self):
pass
def make_os(self):
pass
# -----------具体工厂----------
class ApplePhoneFactory(PhoneFactory):
def make_shell(self):
return AppleShell()
def make_cpu(self):
return AppleCPU()
def make_os(self):
return AppleOS()
class AndroidPhoneFactory(PhoneFactory):
def make_shell(self):
return AndroidShell()
def make_cpu(self):
return AndroidCPU()
def make_os(self):
return AndroidOS()
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)
f = AndroidPhoneFactory()
make_phone(f).show_info()
优缺点:
优点:将客户端与类的具体实现相分离。每个工厂创建一个完整的产品系列,使得易于交换产品系列。有利于产品的一致性(即产品之间的约束关系)
缺点:难以支持新种类的(抽象)产品
建造者模式
内容:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式与抽象工厂模式相似,也用来创建复杂对象。主要区别建造者模式注重一步步建造一个复杂对象,而抽象模式着重于多个系列的产品对象
角色:
抽象建造者(builder)
具体建造者(concrete builder)
指挥者(director)
产品(product)
# 建造者模式
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 "%s,%s,%s,%s" % (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 SexGrilBuilder(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
b = SexGrilBuilder()
p = PlayerDirector().build_player(b)
print(p)
优缺点:
优点:隐藏了一个产品的内部结构和装配过程。将构造代码与解释代码分开。可以对构造过程进行更精细的控制
单例模式
内容:
保证一个类只有一个实例,并提供一个访问它的全局访问点
角色:
单例(singleton)
优缺点:
优点:对唯一实例的受控访问。单例相当于全局变量,但防止了命名空间被污染
# 单例模式
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)
print(b.a)
print(id(a),id(b))
结构型模式(7种)
结构型模式(7种):适配器模式,桥模式,组合模式,装饰模式,外观模式,享元模式,代理模式
适配器模式
内容:
将一个类的接口转化成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。
两种实现方式:
类适配器:使用多继承
对象适配器:使用组合
角色:
目标接口(target)
待适配的类(adaptee)
适配器(adapter)
使用场景:
想使用一个存在的类,而他的接口不符合你的要求
(对象适配器)想使用一些已经存在的子类,但不可能对每一个进行子类化以匹配他们的接口。对适配器可以适配他的父类接口。
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
class Alipay(Payment):
def pay(self, money):
print('苹果支付%s元' % money)
class Wechat(Payment):
def pay(self, money):
print('微信支付%s元' % money)
class Yinlianpay:
def cost(self, money):
print('银联支付%s元' % money)
# ---------类适配器:使用多继承------------
class NewYinlianpay(Payment, Yinlianpay):
def pay(self, money):
self.cost(money)
# ---------类适配器:使用多继承------------
# -----------对象适配器:使用组合------------
class PaymentAdapter(Payment):
def __init__(self, payment):
self.payment = payment
def pay(self, money):
self.payment.cost(money)
# -----------对象适配器:使用组合------------
p = NewYinlianpay()
p.pay(100)
p1 = PaymentAdapter(Yinlianpay())
p1.pay(200)
桥模式
内容:
将一个事物的两个维度分离,使其都可以独立的变化。
角色:
抽象(abstraction)
细化抽象(refinedabstraction)
实现者(implementor)
具体实现者(concreteimplementor)
使用场景:
当事物有两个维度上的表现,两个维度都需要扩展时。
优点:
抽象和实现相分离。
优秀的扩展能力。
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 Red(Color):
def paint(self, shape):
print('红色的%s' % shape.name)
class Green(Color):
def paint(self, shape):
print('绿色的%s' % shape.name)
shape = Rectangle(Red())
shape.draw()
shape2 = Circle(Green())
shape2.draw()
组合模式
内容:
将对象组合成树形结构以表示“整体-部分”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
角色:
抽象组件(component)
叶子组件(leaf)
复合组件(composite)
客户端(client)
使用场景:
表示对象的“部分-整体”层次结构(特别是结构是递归的)
希望用户忽略组合对象和单个对象的不同,用户统一的使用组合结构中的所有对象
优点:
定义了包含基本对象和组合对象的类层次结构
简化客户端代码,即客户端可以一致的使用组合对象和单个对象
更容易增加新类型的组件
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.chirdren = []
for g in iterable:
self.add(g)
def add(self, graghic):
self.chirdren.append(graghic)
def draw(self):
for g in self.chirdren:
g.draw()
p1 = Point(1, 2)
p2 = Point(3, 4)
p3 = Point(5, 6)
p4 = Point(7, 8)
l1 = Line(p1, p2)
l2 = Line(p3, p4)
pic1 = Picture([l1, p1])
pic2 = Picture([pic1, l2, l1, p1, p3])
pic2.draw()
外观模式
内容:
为子系统的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
角色:
外观(facade)
子系统类(subsystem classes)
优点:
减少系统相互依赖
提高了灵活性
提高了安全性
from abc import abstractmethod, ABCMeta
class Systems(metaclass=ABCMeta):
@abstractmethod
def run(self):
pass
def stop(self):
pass
class CPU(Systems):
def run(self):
print('CPU开始运行')
def stop(self):
print('CPU停止运行')
class Disk(Systems):
def run(self):
print('磁盘开始运行')
def stop(self):
print('磁盘停止运行')
class Memory(Systems):
def run(self):
print('内存开始运行')
def stop(self):
print('内存停止运行')
class Computer(Systems):
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()
代理模式
内容:
为其他对象提供一种代理以控制对这个对象的访问
应用场景:
远程代理:为远程的对象提供代理
虚代理:根据需要创建很大的代理
保护代理:控制对原始对象的访问,用于对象有不同访问权限时
角色:
抽象实体(subject)
实体(realsubject)
代理(proxy)
优点:
远程代理:可以隐藏对象位于远程地址空间的事实
虚代理:可以进行优化,例如根据要求创建对象
保护代理:允许在访问一个对象时有一些附加的内务处理
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, filname):
self.filname = filname
f = open(filname, 'r', encoding='utf-8')
self.content = f.read()
f.close()
def get_content(self):
return self.content
def set_content(self, content):
f = open(self.filname, 'w', encoding='utf-8')
f.write(content)
f.close()
#
# subj = RealSubject('test.txt')
# subj.set_content('欢迎你mwn')
# result = subj.get_content()
#
# print(result)
class VirtualProxy(Subject):
def __init__(self, filname):
self.filname = filname
self.subj = None
def get_content(self):
if not self.subj:
self.subj = RealSubject(self.filname)
return self.subj.get_content()
def set_content(self, content):
if not self.subj:
self.subj = RealSubject(self.filname)
return self.subj.set_content(content)
# subj = VirtualProxy('test.txt')
# print(subj.get_content())
class ProtectedProxy(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=ProtectedProxy('test.txt')
print(subj.get_content())
subj.set_content('abc')
行为型模型(11种)
行为型模式(11种):解释器模式,责任链模式,命令模式,迭代器模式,中介者模式,备忘录模式,观察者模式,状态模式,策略模式,访问者模式,模板方法模式
责任链模式
内容:
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
角色:
抽象处理者(handler)
具体处理者(concretehandler)
客户端(client)
适用场景:
有多个对象处理一个请求,哪个对象处理有运行是决定
在不明确接受者的情况下,向多个对象中的一个提交一个请求
优点:
降低耦合度:一个对象无需知道其他那一个对象处理其请求
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("总经理准假%s天" % day)
else:
print('你还是辞职吧')
class DepartmentManager(Handler):
def __init__(self):
self.next = GeneralManager()
def handle_leave(self, day):
if day <= 5:
print("产品经理准假%s天" % day)
else:
print('产品经理权限不足')
self.next.handle_leave(day)
class ProjectDirector(Handler):
def __init__(self):
self.next = DepartmentManager()
def handle_leave(self, day):
if day <= 3:
print("项目主管准假%s天" % day)
else:
print('项目主管权限不足')
self.next.handle_leave(day)
p = ProjectDirector()
p.handle_leave(3)
观察者模式
内容:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都得到通知并得到自动更新。观察者模式又称‘发布订阅模式’
角色:
抽象主题(subject)
具体主题(concretesubject)——发布者
抽象观察者(observe)
具体观察者(concreteobserve)——订阅者
适用场景:
当一个抽象模型有两方面,其中一方面依赖另一方面。将这两者封装在独立对象中以使他们可以各自独立的改变和复用。
当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
当一个对象必须通知其他对象,而他又不能假定其他对象是谁。换言之,你不希望这些对象是紧密耦合的
优点:
目标和观察者之间的抽象耦合最小
支持广播通信
from abc import ABCMeta, abstractmethod
class Observe(metaclass=ABCMeta): # 抽象订阅者
@abstractmethod
def update(self, notice): # notice是一个Notice类的对象
pass
class Notice: # 抽象发布者
def __init__(self):
self.observes = []
def attach(self, obs):
self.observes.append(obs)
def detach(self, obs):
self.observes.remove(obs)
def notify(self): # 推送
for obs in self.observes:
obs.update(self)
class StaffNotice(Notice): # 具体发布者
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() # 推送
# obj = StaffNotice('123')
# obj.company_info = 'zxc'
# print(obj.company_info)
# 具体订阅者
class Staff(Observe):
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.detach(s2)
notice.company_info = '公司明天放假!!!'
print(s1.company_info)
print(s2.company_info)
策略模式
内容:
定义一系列的算法,把他们一个个封装起来,并且使他们可相互替换,本模式使得算法可独立于使用它的客户而变化
角色:
抽象策略(strategy)
具体策略(concretestrategy)
上下文(con'text)
优点:
定义了一系列可重用的算法和行为
消除了一些条件语句
可以提供相同行为的不同实现
缺点:
客户必须了解不同的策略
from abc import ABCMeta, abstractmethod
class Strategy(metaclass=ABCMeta):
@abstractmethod
def execute(self, data):
pass
class FastStrategy(Strategy):
def execute(self, data):
print('用较快的策略处理%s' % data)
class SlowStrategy(Strategy):
def execute(self, data):
print('用较慢的策略处理%s' % 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 = "[...]"
s = FastStrategy()
context = Context(s, data)
context.do_strategy()
模板方法模式
内容:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
角色:
抽象类:定义抽象的原子操作(钩子操作);实现一个模板方法作为算法的骨架。
具体类:实现原子操作
适用场景:
一次性实现一个算法的不变部分
各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复
控制子类扩展
from abc import ABCMeta, abstractmethod
import time
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()
time.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)
MyWindow("窗口信息hello").run()