python常用设计模式
一、设计模式基础
1. 基础知识
-
设计模式:对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计。
-
面向对象的三大特性:
-
封装
-
继承
-
多态
这三大特性顺序不能错,因为他们之间不是并列关系而是递进关系。
-
-
接口:若干抽象方法的集合。
作用:限制实现接口的类必须按照接口给定的调用方式实现这些方法;对高层模块隐藏了类的内部实现。
代码示例:
# 接口方法一: # class Payment: # def pay(self,money): # raise NotImplementedError # 抛出一个没有实现错误,要求继承Payment的类必须实现pay方法 # 接口方法二:常用 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): # abc: abstract class @abstractmethod def pay(self,money): pass class Alipay(Payment): def pay(self, money): print('支付宝支付%d元' % money) class WechatPay(Payment): def pay(self,money): print('微信支付%d元' % money) # p = Alipay() p = WechatPay() p.pay(100)
-
如果一个类里有抽象方法,那么该类就是一个抽象类。上述代码中Payment类有抽象方法def pay(),所以Payment是一个抽象类。
-
上述代码的Alipay类和Wechat类就算底层代码,对类的调用p.pay(100)就属于高层代码(模块),如果有了接口进行限制,编写高层代码的人只需要读懂接口就可以正确调用函数,而不必把底层的每个类是如何实现的挨个看一遍。
2. 面向对象设计SOLID原则
-
单一职责原则(Single Responsibility Principle):不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。
-
开放封闭原则(Open Closed Principle):一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
-
里氏替换原则(Liskov Substitution Principle):所有引用父类的地方必须能透明地使用其子类的对象。
-
接口隔离原则(Interface-Segregation Principles):使用多个专门的接口,而不使用单一的总接口,即客户端(高层模块)不应该依赖那些它不需要的接口。
解释:设计模式中客户端的概念通常是指高层代码(模块),并不是网络通信server、client概念下的客户端。
-
依赖倒置原则(Dependence Inversion Principle):高层模块不应该依赖底层模块,二者都应该依赖其抽象(即接口);抽象不应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程。
解释:这样如果底层代码进行了改动,高层代码(模块)则不用随之改动。抽象就是上述代码的class Payment接口,细节就是class Alipay和class WechatPay,应该是先定义好接口,然后根据接口规则去实现细节;不能先写好细节,根据细节去定义接口。
代码示例:
# 接口隔离原则 class LandAnimal(metaclass=ABCMeta): # 专门的接口(陆地) @abstractmethod def walk(self): pass class WaterAnimal(metaclass=ABCMeta): # 专门的接口(水上) @abstractmethod def swim(self): pass class SkyAnimal(metaclass=ABCMeta): # 专门的接口(天上) @abstractmethod def fly(self): pass class Tiger(LandAnimal): def walk(self): print("老虎走路") class Frog(LandAnimal,WaterAnimal): def walk(self): print("青蛙走路") def swim(self): print("青蛙游泳")
3. 设计模式分类
- 创建型模式(5种):工厂方法模式、抽象工厂模式、创建者模式、原型模式、单例模式。
- 结构型模式(7种):适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式。
- 行为型模式(11种):解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模版方法模式。
4. 简单工厂模式(Simple Factory Pattern)
-
简单工厂模式不属于23种设计模式。
-
内容:不直接向客户端暴露对象创建的实现细节,而是通过一个工厂类来负责创建产品类的实例。
-
角色:
工厂角色(Creator)
抽象产品角色(Product)
具体产品角色(Concrete Product)
代码示例:
# 简单工厂模式
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta): # 抽象产品角色
# abc: abstract class
@abstractmethod
def pay(self,money):
pass
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 WechatPay(Payment): # 具体产品角色
def pay(self,money):
print('微信支付%d元' % money)
class PaymentFactor: # 工厂角色
def creat_payment(self,method):
if method == 'alipay':
return Alipay()
elif method == 'wechat':
return WechatPay()
elif method == 'huabei':
return Alipay(use_huabei=True)
else:
raise TypeError("No such payment named %s" % method)
# client (高层代码模块)
pf = PaymentFactor()
p = pf.creat_payment('huabei')
p.pay(100)
- 优点:
- 隐藏了对象创建的实现细节。
- 客户端client(高层模块)不需要修改代码。
- 缺点:
- 违反了单一职责原则,将创建逻辑集中到一个工厂类里。
- 当添加新产品时,需要修改工厂类代码,违反了开放封闭原则。
二、创建型模式(5种)
1. 工厂方法模式(Factory Pattern)
-
内容:定义一个用于创建对象的接口(工厂接口),让子类决定实例化哪一个产品类。
-
角色:
抽象工厂角色(Creator)
具体工厂角色(Concrete Creator)
抽象产品角色(Product)
具体产品角色(Concrete Product)
代码示例:
# 工厂方法模式
from abc import ABCMeta, abstractmethod
class Payment(metaclass=ABCMeta): # 抽象产品角色
# abc: abstract class
@abstractmethod
def pay(self,money):
pass
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 WechatPay(Payment): # 具体产品角色
def pay(self,money):
print('微信支付%d元' % money)
class BankPay(Payment): # 具体产品角色
def pay(self,money):
print('银行卡支付%d元' % money)
class PaymentFactory(metaclass=ABCMeta): # 抽象工厂角色
@abstractmethod
def creat_payment(self):
pass
class AlipayFactory(PaymentFactory): # 具体工厂角色
def creat_payment(self):
return Alipay()
class WechatpayFactory(PaymentFactory): # 具体工厂角色
def creat_payment(self):
return WechatPay()
class HuabeiFactory(PaymentFactory): # 具体工厂角色
def creat_payment(self):
return Alipay(use_huabei=True)
class BankPayFactory(PaymentFactory): # 具体工厂角色
def creat_payment(self):
return BankPay()
# client (高层代码模块)
pf = HuabeiFactory()
p = pf.creat_payment()
p.pay(<