Python常用设计模式
1 面向对象
1.1 面向对象三大特征
- 封装
- 继承
- 多态
1.2 面向对象设计SOLID原则
- 开放封闭原则:设计面向对象时,保证实现实体的时候尽量不修改原有对象类的代码。
- 里氏替换原则:所有引用父类的地方必须能透明的使用其子类的对象。子类的输入输出与父类保持一致。
- 依赖倒置原则:高层模块不应该依赖底层模块,二者都应该依赖其抽象,抽象不应该依赖于细节,细节依赖于抽象。抽象即接口–黑箱输出输入。
- 接口隔离原则:使用多个专门的接口,而不使用单一的总接口(接口功能颗粒度小,把功能进行拆分,不要一个接口实现综合功能)
- 单一职责原则:不要存在多于一个导致类变更的原因。一个类只负责一项职责。
2 设计模式分类
- 创建型模式:工厂方法模式、抽象工厂模式、创建者模式、原型模式、单例模式
- 结构型模式:适配器模式、桥模式、组合模式、装饰模式、外观模式、享元模式、代理模式
- 行为型模式:解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模板方法模式
3 创建型模式介绍
3.1 简单工厂模式
from abc import ABCMeta,abstractmethod
#产品
class Dog(metaclass=ABCMeta):
@abstractmethod
def __init__(self,name,varieties):
self.name=name
self.varieties=varieties
#工厂
class DogFactory:
def create_dog(self,name,varieties):
'''可以生产各品种的狗'''
return Dog(name,varieties)
factory=DogFactory()
dog_tom=factory.create_dog('Tom','kirky')
特点:一个工厂不止生成一种产品,隐藏了对象创建的实现细节
不足:违反了单一责任原则,将创建逻辑集中到一个工厂类
3.2 工厂模式
#产品
class Dog():
def __init__(self,name,varieties):
self.name=name
self.varieties=varieties
#柯基工厂
class KirkyFactory:
def __init__(self):
self.varieties='kirky'
def create_dog(self,name):
'''可以生产各品种的狗'''
return Dog(name,self.varieties)
factory=KirkyFactory()
dog_tom=factory.create_dog('Tom')
特点:一个工厂生产一种产品
不足:每增加一个具体产品类,就必须增加一个相应的具体工厂类。
3.3 抽象工厂模式
from abc import abstractmethod
#产品抽象基类
class CPU:
'''CPU抽象类'''
@abstractmethod
def create_cpu(self):
pass
class OS:
'''操作系统抽象类'''
@abstractmethod
def create_os(self):
pass
#产品
class QualcommCPU(CPU):
def create_cpu(self):
print('高通CPU')
class AppleCPU(CPU):
def create_cpu(self):
print('苹果CPU')
class IOS(OS):
def create_os(self):
print('苹果IOS')
class Android(OS):
def create_os(self):
print('安卓Android')
#抽象工厂
class PhoneFactory:
'''手机工厂,需要CPU函数以及OS操作系统函数'''
@abstractmethod
def create_cpu(self):
pass
@abstractmethod
def create_os(self):
pass
#工厂
class AppleFactory(PhoneFactory):
'''苹果工厂:苹果CPU和IOS系统'''
def create_cpu(self):
return AppleCPU()
def create_os(self):
return IOS()
class MiFactory(PhoneFactory):
'''小米工厂:高通CPU和安卓系统'''
def create_cpu(self):
return QualcommCPU()
def create_os(self):
return Android()
角色包含:抽象产品、产品、抽象工厂、工厂、客户端
使用抽象工厂作为基类,每个工厂生产一套产品,而非一种产品
优点:
- 产品可复用,工厂可以方便的更换产品
- 有利于产品的一致性,保持产品之间的约束关系(例如IOS系统和苹果CPU之间约束关系)
缺点:
- 增加抽象产品的话代码改动较大、需要修改抽象工厂以及所有的具体工厂。
3.4 建造者模式
from abc import abstractmethod,ABCMeta
# 玩家基类
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 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
builder = MonsterBuilder()#创建者
director = PlayerDirector()#指挥者
p = director.build_player(builder)
print(p)
优点:
- 隐藏了产品内部结构和装配过程
- 将构造代码与代表代码分开
- 可以对构造过程就行更加精细的控制
3.5 单例模式
保证一个类就只有一个实例,并提供一个访问它的全局访问点。
Python的模块为天生的实例。
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)
4 结构型模式
适配器模式
使得原本不兼容的接口增加一个类,使得相互兼容
from abc import abstractmethod, ABCMeta
#产品
class Dog():
def __init__(self, name, varieties):
self.name = name
self.varieties = varieties
#工厂基类
class Factory(metaclass=ABCMeta):
@abstractmethod
def create_dog(self,name):
pass
# 具体工厂
class KirkyFactory(Factory):
def __init__(self):
self.varieties = 'kirky'
def create_dog(self, name):
return Dog(name, self.varieties)
#待适配的类
class HuskyFactory:
def __init__(self):
self.varieties = 'Husky'
def get_dog(self, name):
return Dog(name, self.varieties)
#适配器
class NewFactory(Factory):
def __init__(self, factory):
self.factory = factory
def create_dog(self, name):
return self.factory.get_dog(name)
dog_tim = NewFactory(HuskyFactory())
dog1=dog_tim.create_dog('Tim')
print(dog1.name)
桥模式
将一个事物的两个维度分离,使其都可以独立变化。
from abc import abstractmethod, ABCMeta
class Shape(metaclass=ABCMeta):
def __init__(self,color):
self.color=color
@abstractmethod
def drew(self):
pass
class Color(metaclass=ABCMeta):
@abstractmethod
def paint(self,shape):
pass
class Red(Color):
def paint(self,shape):
print('红色的%s'% shape.name)
class Rectangle(Shape):
self.name='长方形'
def draw(self):
self.color.paint(self)
rectangle=Rectangle(Red())
rectangle.drew()