python常用设计模式
创建型模式
1 工厂模式
简单工厂模式:一个工厂可以生成多个对象
class Shape(object):
def draw(self):
raise NotImplementedError
class Circle(Shape):
def draw(self):
print('draw circle')
class Rectangle(Shape):
def draw(self):
print('draw Rectangle')
class ShapeFactory(object):
def create(self, shape):
if shape == 'Circle':
return Circle()
elif shape == 'Rectangle':
return Rectangle()
else:
return None
fac = ShapeFactory()
obj = fac.create('Circle')
obj.draw()
未使用模式:
class Shape(object):
pass
class Triangle(Shape):
def draw(self):
print("画三角形")
class Square(Shape):
def draw(self):
print("画正方形")
s1 = Triangle()
s2 = Square()
s1.draw()
s2.draw()
工厂方法模式:多个工厂,一个工厂生产一个对象
#_*_coding:utf-8_*_
'''
工厂方法模式是简单工厂模式的衍生,解决了许多简单工厂模式的问题。
首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。
工厂方法模式的对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不在负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。在这个模式中,工厂类和产品类往往可以依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
工厂方法模式(Factory Method pattern)是最典型的模板方法模式(Templete Method pattern)应用。
'''
class CreateOperation(object):
def get_name(self):
return self.Operation_name
class Addition(CreateOperation):
def __init__(self):
self.Operation_name = 'Addition'
def count(self):
print("加法计算")
class Subtraction(CreateOperation):
def __init__(self):
self.Operation_name = 'Subtraction'
def count(self):
print("减法计算")
class OperationInterfaceFactory(object):
'''接口基类'''
def create(self):
'''把要创建的工厂对象装配进来'''
raise NotImplementedError
class CreateAddition(OperationInterfaceFactory):
def create(self):
return Addition()
class CreateSubtraction(OperationInterfaceFactory):
def create(self):
return Subtraction()
shape_interface = CreateAddition()
obj = shape_interface.create()
obj.get_name()
obj.count()
shape_interface2 = CreateSubtraction()
obj2 = shape_interface2.create()
obj2.count()
抽象工厂模式:多个工厂,一个工厂生产多种同一品牌的产品,为同一产品簇;不同工厂生产的同种结构的产品,为同一等级结构。
通过使用抽象工厂模式,可以处理具有相同(或者相似)等级结构中的多个产品族中的产品对象的创建问题。如下图所示:
由于这两个产品族的等级结构相同,因此使用同一个工厂族也可以处理这两个产品族的创建问题,这就是抽象工厂模式。
抽象工厂的功能是为一系列相关对象或相互依赖的对象创建一个接口。一定要注意,这个接口内的方法不是任意堆砌的,而是一系列相关或相互依赖的方法。
在什么情况下应当使用抽象工厂模式
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
- 这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
- 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。(比如:Intel主板必须使用Intel CPU、Intel芯片组)
- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
#_*_coding:utf-8_*_
class AbstractFactory(object):
computer_name = ''
def createCpu(self):
pass
def createMainboard(self):
pass
class IntelFactory(AbstractFactory):
computer_name = 'Intel I7-series computer '
def createCpu(self):
return IntelCpu('I7-6500')
def createMainboard(self):
return IntelMainBoard('Intel-6000')
class AmdFactory(AbstractFactory):
computer_name = 'Amd 4 computer '
def createCpu(self):
return AmdCpu('amd444')
def createMainboard(self):
return AmdMainBoard('AMD-4000')
class AbstractCpu(object):
series_name = ''
instructions = ''
arch=''
class IntelCpu(AbstractCpu):
def __init__(self,series):
self.series_name = series
class AmdCpu(AbstractCpu):
def __init__(self,series):
self.series_name = series
class AbstractMainboard(object):
series_name = ''
class IntelMainBoard(AbstractMainboard):
def __init__(self,series):
self.series_name = series
class AmdMainBoard(AbstractMainboard):
def __init__(self,series):
self.series_name = series
class ComputerEngineer(object):
def makeComputer(self,factory_obj):
self.prepareHardwares(factory_obj)
def prepareHardwares(self,factory_obj):
self.cpu = factory_obj.createCpu()
self.mainboard = factory_obj.createMainboard()
info = '''------- computer [%s] info:
cpu: %s
mainboard: %s
-------- End --------
'''% (factory_obj.computer_name,self.cpu.series_name,self.mainboard.series_name)
print(info)
if __name__ == "__main__":
engineer = ComputerEngineer()
intel_factory = IntelFactory()
engineer.makeComputer(intel_factory)
amd_factory = AmdFactory()
engineer.makeComputer(amd_factory)
2.建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
#建造者模式
#相关模式:思路和模板方法模式很像,模板方法是封装算法流程,对某些细节,提供接口由子类修改,建造者模式更为高层一点,将所有细节都交由子类实现。
# 建造者模式:将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。
# 基本思想
# 某类产品的构建由很多复杂组件组成;
# 这些组件中的某些细节不同,构建出的产品表象会略有不同;
# 通过一个指挥者按照产品的创建步骤来一步步执行产品的创建;
# 当需要创建不同的产品时,只需要派生一个具体的建造者,重写相应的组件构建方法即可。
def printInfo(info):
print(info)
#建造者基类
class PersonBuilder():
def BuildHead(self):
pass
def BuildBody(self):
pass
def BuildArm(self):
pass
def BuildLeg(self):
pass
#胖子
class PersonFatBuilder(PersonBuilder):
type = '胖子'
def BuildHead(self):
printInfo("构建%s的大。。。。。头" % self.type)
def BuildBody(self):
printInfo("构建%s的身体" % self.type)
def BuildArm(self):
printInfo("构建%s的手" % self.type)
def BuildLeg(self):
printInfo("构建%s的脚" % self.type)
#瘦子
class PersonThinBuilder(PersonBuilder):
type = '瘦子'
def BuildHead(self):
printInfo("构建%s的头" % self.type)
def BuildBody(self):
printInfo("构建%s的身体" % self.type)
def BuildArm(self):
printInfo("构建%s的手" % self.type)
def BuildLeg(self):
printInfo("构建%s的脚" % self.type)
#指挥者
class PersonDirector():
pb = None;
def __init__(self, pb):
self.pb = pb
def CreatePereson(self):
self.pb.BuildHead()
self.pb.BuildBody()
self.pb.BuildArm()
self.pb.BuildLeg()
if __name__ == '__main__':
pb = PersonThinBuilder()
pd = PersonDirector(pb)
pd.CreatePereson()
pb2 = PersonFatBuilder()
#pd = PersonDirector(pb)
pd.pb = pb2
pd.CreatePereson()
3.单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
#实现__new__方法
#并在将一个类的实例绑定到类变量_instance上,
#如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回
#如果cls._instance不为None,直接返回cls._instance
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls,'_instance'):
orig = super(Singleton,cls)
cls._instance = orig.__new__(cls)
return cls._instance
class MyClass(Singleton):
def __init__(self,name):
self.name = name
a = MyClass("Alex")
b = MyClass("Jack")
print(a.name)
print(b.name)
结构型模式
1.适配器模式
将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
#_*_coding:utf-8_*_
#适配器模式
# 将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
# 应用场景:希望复用一些现存的类,但是接口又与复用环境要求不一致。
def printInfo(info):
print(info)
#球员类
class Player():
name = ''
def __init__(self,name):
self.name = name
def Attack(self,name):
pass
def Defense(self):
pass
#前锋
class Forwards(Player):
def __init__(self,name):
Player.__init__(self,name)
def Attack(self):
printInfo("前锋%s 进攻" % self.name)
def Defense(self):
printInfo("前锋%s 防守" % self.name)
#中锋(目标类)
class Center(Player):
def __init__(self,name):
Player.__init__(self,name)
def Attack(self):
printInfo("中锋%s 进攻" % self.name)
def Defense(self):
printInfo("中锋%s 防守" % self.name)
#后卫
class Guards(Player):
def __init__(self,name):
Player.__init__(self,name)
def Attack(self):
printInfo("后卫%s 进攻" % self.name)
def Defense(self):
printInfo("后卫%s 防守" % self.name)
#外籍中锋(待适配类)
#中锋
class ForeignCenter(Player):
name = ''
def __init__(self,name):
Player.__init__(self,name)
def ForeignAttack(self):
printInfo("外籍中锋%s 进攻" % self.name)
def ForeignDefense(self):
printInfo("外籍中锋%s 防守" % self.name)
#翻译(适配类)
class Translator(Player):
foreignCenter = None
def __init__(self,name):
self.foreignCenter = ForeignCenter(name)
def Attack(self):
self.foreignCenter.ForeignAttack()
def Defense(self):
self.foreignCenter.ForeignDefense()
if __name__ == '__main__':
b = Forwards('巴蒂尔')
ym = Guards('姚明')
m = Translator('麦克格雷迪')
b.Attack()
ym.Attack()
m.Attack()
2.桥接模式
将抽象部分与实现部分分离,使它们都可以独立的变化。
class AbstractRoad(object):
'''路基类'''
car = None
class AbstractCar(object):
'''车辆基类'''
def run(self):
raise NotImplementedError
class Street(AbstractRoad):
'''市区街道'''
def run(self):
self.car.run()
print("在市区街道上行驶")
class SpeedWay(AbstractRoad):
'''高速公路'''
def run(self):
self.car.run()
print("在高速公路上行驶")
class Car(AbstractCar):
'''小汽车'''
def run(self):
print("小汽车在")
class Bus(AbstractCar):
'''公共汽车'''
def run(self):
print("公共汽车在")
if __name__ == "__main__":
#小汽车在高速上行驶
road1 = SpeedWay()
road1.car = Car()
road1.run()
road2 = SpeedWay()
road2.car = Bus()
road2.run()
road3 = Street()
road3.car = Bus()
road3.run()
3.组合模式
将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。
# 应用组合模式的会员卡消费
# 那么我们就根据我们会员卡的消费,来模拟一下组合模式的实现吧!let's go!
# 首先:
# 1.我们的部件有,总店,分店,加盟店!
# 2.我们的部件共有的行为是:刷会员卡
# 3.部件之间的层次关系,也就是店面的层次关系是,总店下有分店、分店下可以拥有加盟店。
#
# 有了我们这几个必要条件后,我的要求就是目前店面搞活动当我在总店刷卡后,就可以累积相当于在所有下级店面刷卡的积分总额,设计的代码如下
class Store(object):
'''店面基类'''
#添加店面
def add(self,store):
pass
#删除店面
def remove(self,store):
pass
def pay_by_card(self):
pass
class BranchStore(Store):
def __init__(self,name):
self.name = name
self.my_store_list = []
def pay_by_card(self):
print("店面[%s]的积分已累加进该会员卡" %self.name)
for s in self.my_store_list:
s.pay_by_card()
#添加店面
def add(self,store):
self.my_store_list.append(store)
#删除店面
def remove(self,store):
self.my_store_list.remove(store)
class JoinStore(Store):
'''加盟店'''
def __init__(self,name):
self.name = name
def pay_by_card(self):
print("店面[%s]的积分已累加进该会员卡" %self.name)
def add(self,store):
print("无添加子店权限")
def remove(self,store):
print("无删除子店权限")
if __name__ == "__main__":
store = BranchStore("朝阳总店")
branch = BranchStore("海淀分店")
join_branch = JoinStore("昌平加盟1店")
join_branch2 = JoinStore("昌平加盟2店")
branch.add(join_branch)
branch.add(join_branch2)
store.add(branch)
store.pay_by_card()
print(store.my_store_list)
# 这样在累积所有子店面积分的时候,就不需要去关心子店面的个数了,也不用关系是否是叶子节点还是组合节点了,也就是说不管是总店刷卡,还是加盟店刷卡,都可以正确有效的计算出活动积分。
# 什么情况下使用组合模式
# 引用大话设计模式的片段:“当发现需求中是体现部分与整体层次结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑组合模式了。”
4.外观模式
为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
#_*_coding:utf-8_*_
#外观模式(Facade),为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用。
# 在以下情况下可以考虑使用外观模式:
# (1)设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观模式。
# (2) 开发阶段,子系统越来越复杂,增加外观模式提供一个简单的调用接口。
# (3) 维护一个大型遗留系统的时候,可能这个系统已经非常难以维护和扩展,但又包含非常重要的功能,为其开发一个外观类,以便新系统与其交互。
# 优点编辑
# (1)实现了子系统与客户端之间的松耦合关系。
# (2)客户端屏蔽了子系统组件,减少了客户端所需处理的对象数目,并使得子系统使用起来更加容易。
def printInfo(info):
print(info)
class Stock():
name = '股票'
def buy(self):
printInfo('买 '+self.name)
def sell(self):
printInfo('卖 '+self.name)
class ETF():
name = '指数型基金'
def buy(self):
printInfo('买 '+self.name)
def sell(self):
printInfo('卖 '+self.name)
class Future():
name = '期货'
def buy(self):
printInfo('买 '+self.name)
def sell(self):
printInfo('卖 '+self.name)
class NationDebt():
name = '国债'
def buy(self):
printInfo('买 '+self.name)
def sell(self):
printInfo('卖 '+self.name)
class Option():
name = '权证'
def buy(self):
printInfo('买 '+self.name)
def sell(self):
printInfo('卖 '+self.name)
#基金
class Fund():
def __init__(self):
self.stock = Stock()
self.etf = ETF()
self.future = Future()
self.debt = NationDebt()
self.option = Option()
def buyFund(self):
self.stock.buy()
self.etf.buy()
self.debt.buy()
self.future.buy()
self.option.buy()
def sellFund(self):
self.stock.sell()
self.etf.sell()
self.future.sell()
self.debt.sell()
self.option.sell()
if __name__ == '__main__':
myFund = Fund()
myFund.buyFund()
myFund.sellFund()
5.享元模式
运用共享技术有效地支持大量细粒度的对象。
原文链接:https://blog.csdn.net/qq_21467113/article/details/89480740
6.代理模式
为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
#_*_coding:utf-8_*_
# 代理模式
# 应用特性:需要在通信双方中间需要一些特殊的中间操作时引用,多加一个中间控制层。
# 结构特性:建立一个中间类,创建一个对象,接收一个对象,然后把两者联通起来
class sender_base:
def __init__(self):
pass
def send_something(self, something):
pass
class send_class(sender_base):
def __init__(self, receiver):
self.receiver = receiver
def send_something(self, something):
print("SEND " + something + ' TO ' + self.receiver.name)
class agent_class(sender_base):
def __init__(self, receiver):
self.send_obj = send_class(receiver)
def send_something(self, something):
self.send_obj.send_something(something)
class receive_class:
def __init__(self, someone):
self.name = someone
if '__main__' == __name__:
receiver = receive_class('Alex')
agent = agent_class(receiver)
agent.send_something('agentinfo')
print(receiver.__class__ )
print(agent.__class__ )
1.模板方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
class Register(object):
'''用户注册接口'''
def register(self):
pass
def login(self):
pass
def auth(self):
self.register()
self.login()
class RegisterByQQ(Register):
'''qq注册'''
def register(self):
print("---用qq注册-----")
def login(self):
print('----用qq登录-----')
class RegisterByWeiChat(Register):
'''微信注册'''
def register(self):
print("---用微信注册-----")
def login(self):
print('----用微信登录-----')
if __name__ == "__main__":
register1 = RegisterByQQ()
register1.auth()
register2 = RegisterByWeiChat()
register2.auth()
2.责任链模式
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
#_*_coding:utf-8_*_
# 职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
# 适用场景:
# 1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;
# 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
# 3、处理一个请求的对象集合应被动态指定。
class BaseHandler(object):
'''处理基类'''
def successor(self,successor): #next_handler
#与下一个责任者关联
self._successor = successor
class RequestHandlerL1(BaseHandler):
'''第一级请求处理者'''
name = "TeamLeader"
def handle(self,request):
if request < 500 :
print("审批者[%s],请求金额[%s],审批结果[审批通过]"%(self.name,request))
else:
print("\033[31;1m[%s]无权审批,交给下一个审批者\033[0m" %self.name)
self._successor.handle(request)
class RequestHandlerL2(BaseHandler):
'''第二级请求处理者'''
name = "DeptManager"
def handle(self,request):
if request < 5000 :
print("审批者[%s],请求金额[%s],审批结果[审批通过]"%(self.name,request))
else:
print("\033[31;1m[%s]无权审批,交给下一个审批者\033[0m" %self.name)
self._successor.handle(request)
class RequestHandlerL3(BaseHandler):
'''第三级请求处理者'''
name = "CEO"
def handle(self,request):
if request < 10000 :
print("审批者[%s],请求金额[%s],审批结果[审批通过]"%(self.name,request))
else:
print("\033[31;1m[%s]要太多钱了,不批\033[0m"%self.name)
#self._successor.handle(request)
class RequestAPI(object):
h1 = RequestHandlerL1()
h2 = RequestHandlerL2()
h3 = RequestHandlerL3()
h1.successor(h2)
h2.successor(h3)
def __init__(self,name,amount):
self.name = name
self.amount = amount
def handle(self):
'''统一请求接口'''
self.h1.handle(self.amount)
if __name__ == "__main__":
r1 = RequestAPI("Alex",9000)
r1.handle()
print(r1.__dict__)
3.观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
#_*_coding:utf-8_*_
__author__ = 'Alex Li'
#
# 观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式
# 当我们希望一个对象的状态发生变化,那么依赖与它的所有对象都能相应变化(获得通知),那么就可以用到Observer模式, 其中的这些依赖对象就是观察者的对象,那个要发生变化的对象就是所谓’观察者’
class ObserverBase(object):
'''观察者基类''' #放哨者
def __init__(self):
self._observerd_list = [] #被通知对象
def attach(self,observe_subject):
'''
添加要观察的对象
:param observe_subject:
:return:
'''
if observe_subject not in self._observerd_list:
self._observerd_list.append(observe_subject)
print("[%s]已经将[%s]加入观察队列..."%(self.name,observe_subject) )
def detach(self,observe_subject):
'''
解除观察关系
:param observe_subject:
:return:
'''
try:
self._observerd_list.remove(observe_subject)
print("不再观察[%s]" %observe_subject)
except ValueError:
pass
def notify(self):
'''
通知所有被观察者
:return:
'''
for objserver in self._observerd_list:
objserver.update(self)
class Observer(ObserverBase):
'''观察者类'''
def __init__(self,name):
super(Observer,self).__init__()
self.name = name
self._msg = ''
@property
def msg(self):
'''
当前状况
:return:
'''
return self._msg
@msg.setter
def msg(self,content):
self._msg = content
self.notify()
class GCDViewer(object):
'''
共军被观察者
'''
def update(self,observer_subject):
print("共军:收到[%s]消息[%s] "%(observer_subject.name,observer_subject.msg) )
class GMDViewer(object):
'''
国军被观察者
'''
def update(self,observer_subject):
print("国军:收到[%s]消息[%s] "%(observer_subject.name,observer_subject.msg) )
if __name__ == "__main__":
observer1 = Observer("共军放哨者")
observer2 = Observer("国军放哨者")
gongjun1 = GCDViewer()
guojun1 = GMDViewer()
observer1.attach(gongjun1)
observer1.attach(guojun1)
observer2.attach(guojun1)
observer1.msg = "\033[32;1m敌人来了...\033[0m"
observer2.msg ="\033[31;1m前方发现敌人,请紧急撤离,不要告诉共军\033[0m"
4.策略模式
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
#_*_coding:utf-8_*_
class TravelStrategy(object):
'''
出行策略
'''
def travelAlgorithm(self):
pass
class AirplaneStrategy(TravelStrategy):
def travelAlgorithm(self):
print("坐飞机出行....")
class TrainStrategy(TravelStrategy):
def travelAlgorithm(self):
print("坐高铁出行....")
class CarStrategy(TravelStrategy):
def travelAlgorithm(self):
print("自驾出行....")
class BicycleStrategy(TravelStrategy):
def travelAlgorithm(self):
print("骑车出行....")
class TravelInterface(object):
def __init__(self,travel_strategy):
self.travel_strategy = travel_strategy
def set_strategy(self,travel_strategy):
self.travel_strategy = travel_strategy
def travel(self):
return self.travel_strategy.travelAlgorithm()
#坐飞机
travel = TravelInterface(AirplaneStrategy())
travel.travel()
#改开车
travel.set_strategy(CarStrategy())
travel.travel()