装饰器模式

装饰器模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。

代码示例

#coding:utf-8
#装饰器模式

class Beverage():
   name = ""
   price = 0.0
   type = "BEVERAGE"
   def getPrice(self):
       return self.price
   def setPrice(self,price):
       self.price = price
   def getName(self):
       return self.name

class coke(Beverage):
   def __init__(self):
       self.name = "coke"
       self.price = 4.0

class milk(Beverage):
   def __init__(self):
       self.name = "milk"
       self.price = 5.0

class drinkDecorator():
   def getName(self):
       pass
   def getPrice(self):
       pass

class iceDecorator(drinkDecorator):
   def __init__(self,Beverage):
       self.beverage = Beverage
   def getName(self):
       return self.beverage.getName() + "  + ice"
   def getPrice(self):
       return self.beverage.getPrice() + 0.4

class sugarDecorator(drinkDecorator):
   def __init__(self,Beverage):
       self.beverage = Beverage
   def getName(self):
       return  self.beverage.getName() + "  + sugar"
   def getPrice(self):
       return self.beverage.getPrice() + 0.8

if __name__ == "__main__":
   milk1 = milk()
   print(milk1.getPrice(),milk1.getName())
   iceMilk = iceDecorator(milk1)
   print(iceMilk.getPrice(),iceMilk.getName())
   cofe1 = coke()
   print(cofe1.getPrice(),cofe1.getName())
   sugarCofe = sugarDecorator(cofe1)
   print(sugarCofe.getPrice(),sugarCofe.getName())

代码解读

该例子基于的需求:客户点饮料系统,在用户下单的过程中,可以对饮料进行相应的定制。

1、先定义了Beverage类,所有的饮料都是由该类继承而来;

2、定义drinkDecorator类,所有需要新增的功能都是由该类继承而来;

3、定义了iceDecorator类,对所点的饮料进行加冰,并且加冰后价格也需要增加;定义了sugarDecorator类,对所点的饮料进行加糖,并且加糖后价格也需要增加。

4、在客户端调用时,先生成milk1实例,然后在对milk1加冰的过程中,在iceDecorator初始化的时候就将milk1实例传入,在调用getName和getPrice时,调用milk1实例的方法后,接着处理milk1方法返回的结果,从而达到动态的更改getName和getPrice方法。

装饰器模式应用场景:

需要扩展、增强或者减弱一个类的功能。

优点

1、装饰器模式时继承方式的一个替代方案,可以轻量级的扩展被装饰对象的功能;

2、Python的装饰器模式是实现AOP的一种方式,便于相同操作位于不同调用为止的统一管理。

缺点

1、多层装饰器的调试和维护较困难。

Python装饰器模式的通用代码

def drugPrice(func):
   def wrapper(self,*args,**kwargs):
       print(self,args,kwargs)
       self.price += 2
       return func(self,*args,**kwargs)
   return wrapper

class Food():
   def __init__(self):
       self.price = 1
   @drugPrice
   def getPrice(self):
       return self.price

if __name__ == "__main__":
   f = Food()
   print(f.getPrice())

python 中的装饰器编写过程: 
先定义装饰器函数

def drugPrice(func):
   def wrapper(self,*args,**kwargs):
       print(self,args,kwargs)
       self.price += 2
       return func(self,*args,**kwargs)
   return wrapper

该函数的调用过程如下: 
当调用drugPrice(func)函数时,返回的是wrapper函数,该函数是func(self,*args,**kwargs),在wrapper(self,*args,**kwargs)的时候,就是调用的func(self,*args,**kwargs)函数,只不过此时还执行了print(self,args,kwargs);self.price += 2这段语句。

@drugPrice
def getPrice(self):
   return self.price

@drugPrice会被Python解析为getPrice=drugPrice(getPrice),此时可以理解为如下的执行顺序

def getPrice(self):
   return self.price
getPrice=drugPrice(getPrice)

然后调用getPrice()函数就会把装饰器里面的内容执行完成。


识别图中二维码,领取python全套视频资料

Python设计模式-装饰器模式的更多相关文章

  1. JAVA设计模式--装饰器模式

    装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

  2. C#设计模式--装饰器模式

    0.C#设计模式-简单工厂模式 1.C#设计模式--工厂方法模式 2.C#设计模式--抽象工厂模式 3.C#设计模式--单例模式 4.C#设计模式--建造者模式 5.C#设计模式--原型模式 6.C# ...

  3. 从ES6重新认识JavaScript设计模式: 装饰器模式

    1 什么是装饰器模式 向一个现有的对象添加新的功能,同时又不改变其结构的设计模式被称为装饰器模式(Decorator Pattern),它是作为现有的类的一个包装(Wrapper). 可以将装饰器理解 ...

  4. C#设计模式-装饰器模式(Decorator Pattern)

    引言 当我们完成一个软件产品开发后就需要对其进行各种测试,适配快速迭代下质量的保障.当有一个完善的产品的对象后,如果我们想要给他添加一个测试功能,那么我们可以用一个新的类去装饰它来实现对原有对象职责的 ...

  5. 设计模式-装饰器模式(Decrator Model)

    文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/6057666.html 目录 1.概述 2.目的 3.结构组成 4.实现 5.总结 1.概 ...

  6. php设计模式 装饰器模式

    装饰器模式,可以动态地添加修改类的功能. 一个类提供了一项功能,如果要修改并添加额外的功能,传统的编程模式需要写一个子类继承它,并重新实现类的方法.使用装饰器模式,仅需要在运行时添加一个装饰器对象即可 ...

  7. 说说设计模式~装饰器模式(Decorator)

    返回目录 装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序, ...

  8. 说说设计模式~装饰器模式(Decorator)~多功能消息组件的实现

    返回目录 为何要设计多功能消息组件 之前写过一篇装饰器模式的文章,感觉不够深入,这次的例子是实现项目中遇到的,所以把它拿出来,再写写,之前也写过消息组件的文章,主要采用了策略模式实现的,即每个项目可以 ...

  9. Java设计模式--装饰器模式到Java IO 流

    装饰器模式 抽象构件角色:给出一个抽象接口,以规范准备接受附加责任的对象. 具体构件角色:定义准备接受附加责任的对象. 抽象装饰角色:持有一个构件对象的实例,并对应一个与抽象构件接口一致的接口. 具体 ...

随机推荐

  1. ORACLE 中 TRANSLATE的用法

    --TRANSLATE(string,from_str,to_str) --to_str和from_str中的字符一一对应 --如果string里有,from_str字符集里没有的字符,将保留 --如 ...

  2. PHPCMS v9.6.0后台getshell

    思路来自于 http://www.cnbraid.com/2016/09/18/phpcms/ 这里自己复现了一下,自己写了一下 因为是后台的,还得登陆两次..所以不好用,主要是学习学习 漏洞来自于R ...

  3. 1.3 Services - 服务

    服务是一种应用组件,它可以在后台执行耗时的操作,它是没有用户界面的.其它的应用组件都可以开启一个服务,服务开启后,即使用户离开了应用,服务仍然可以在后台运行.此外,绑定到服务的组件可以与服务进行交互, ...

  4. Chapter 2 JavaScript Basic

    Has 5 primitive types: Undefined, Null, Boolean, String, Number. typeof  operator Undefined return u ...

  5. linux内核开机logo显示调试

    要使内核支持开机logo显示需要配置内核 配置如下: make menuconfig: Device Drivers  --->     Graphics support  --->    ...

  6. VM克隆之后启动eth0找不到eth0:unknown interface:no such device

    问题出现:VMware 克隆之后,ifconfig命令执行找不到eth0,报错 eth0:unknown interface:no such device 是因为/etc/sysconf/networ ...

  7. SQLServer 批量备份与还原

    备份与还原是数据库避不开的主题,而作为DBA,经常会面临将一台机器上的所有数据库重新构建到一台新机器上的要求: 在现在都讲究自动化管理的时代,传统的界面操作备份还原的做法不仅浪费时间和精力,而且还很容 ...

  8. 禁用LinkButton的方法

    1.服务器端,使用Enabled属性即可 <asp:LinkButton ID="lbtn" runat="server" Enabled="f ...

  9. 《linux系统及其编程》实验课记录(二)

    实验 2:获取对使用命令的帮助 实验环境: 安装了 Red Hat Enterprise Linux 6.0 可运行系统,并且是成功验证系统.有另外一个无特权用户 student,密码 student ...

  10. MathType可以编辑带圈乘号吗

    在数学中有很多符号,可能这些符号我们用得上,也有些符号我们很少用,甚至用不上,但是我们用不上,不代表不存在这个符号,也不代表别人用不上,只是各自所涉及到的知识领域不一样而已.而对于加减乘除运算,几乎每 ...