Python设计模式-装饰器模式
装饰器模式
装饰器模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更为灵活。
代码示例
#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设计模式-装饰器模式的更多相关文章
- JAVA设计模式--装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...
- C#设计模式--装饰器模式
0.C#设计模式-简单工厂模式 1.C#设计模式--工厂方法模式 2.C#设计模式--抽象工厂模式 3.C#设计模式--单例模式 4.C#设计模式--建造者模式 5.C#设计模式--原型模式 6.C# ...
- 从ES6重新认识JavaScript设计模式: 装饰器模式
1 什么是装饰器模式 向一个现有的对象添加新的功能,同时又不改变其结构的设计模式被称为装饰器模式(Decorator Pattern),它是作为现有的类的一个包装(Wrapper). 可以将装饰器理解 ...
- C#设计模式-装饰器模式(Decorator Pattern)
引言 当我们完成一个软件产品开发后就需要对其进行各种测试,适配快速迭代下质量的保障.当有一个完善的产品的对象后,如果我们想要给他添加一个测试功能,那么我们可以用一个新的类去装饰它来实现对原有对象职责的 ...
- 设计模式-装饰器模式(Decrator Model)
文 / vincentzh 原文连接:http://www.cnblogs.com/vincentzh/p/6057666.html 目录 1.概述 2.目的 3.结构组成 4.实现 5.总结 1.概 ...
- php设计模式 装饰器模式
装饰器模式,可以动态地添加修改类的功能. 一个类提供了一项功能,如果要修改并添加额外的功能,传统的编程模式需要写一个子类继承它,并重新实现类的方法.使用装饰器模式,仅需要在运行时添加一个装饰器对象即可 ...
- 说说设计模式~装饰器模式(Decorator)
返回目录 装饰器模式,也叫又叫装饰者模式,顾名思义,将一个对象进行包裹,包装,让它变成一个比较满意的对象,这种模式在我们平时项目开发中,经常会用到,事实上,它是处理问题的一种技巧,也很好的扩展了程序, ...
- 说说设计模式~装饰器模式(Decorator)~多功能消息组件的实现
返回目录 为何要设计多功能消息组件 之前写过一篇装饰器模式的文章,感觉不够深入,这次的例子是实现项目中遇到的,所以把它拿出来,再写写,之前也写过消息组件的文章,主要采用了策略模式实现的,即每个项目可以 ...
- Java设计模式--装饰器模式到Java IO 流
装饰器模式 抽象构件角色:给出一个抽象接口,以规范准备接受附加责任的对象. 具体构件角色:定义准备接受附加责任的对象. 抽象装饰角色:持有一个构件对象的实例,并对应一个与抽象构件接口一致的接口. 具体 ...
随机推荐
- java中调用数据库中的存储过程和函数
public static void main(String[] args) { Connection conn =getConnection(url,user, pwd); ...
- xgboost 安装
git clone --recursive https://github.com/dmlc/xgboostcd xgboost/make -j4 cd python-package/ python s ...
- html 基本标签 ---特殊格式
<address> </address> 地址 <blockquote> </blockquote> 缩进 <q> </q> 小 ...
- extjs,ComboReturn
package cn.edu.hbcf.common.vo; import java.io.Serializable; public class ComboReturn implements Seri ...
- hdu3667 Transportation 费用与流量平方成正比的最小流 拆边法+最小费用最大流
/** 题目:hdu3667 Transportation 拆边法+最小费用最大流 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3667 题意:n个城市由 ...
- RMAN 总括 组成 配置 检测
RMAN 组件: 1. RMAN 执行程序, 也就是RMAN 命令. 2. Server session : 服务器上的进程, 是真正用来干活的. 3. Target database: 你想要进行备 ...
- 第一百三十六节,JavaScript,封装库--事件绑定
JavaScript,封装库--事件绑定 在函数库添加两个函数 添加事件绑定函数 删除事件绑定函数 添加事件绑定函数 /** addEvent()函数库函数,跨浏览器添加事件绑定,注意:传入事件名称时 ...
- HTML5 选择前置摄像头,选择后置摄像头
最近发现我写的都是乱七八糟的,觉得应该给大家带点福利,于是写了这篇 背景:最近想做个web应用,需要用到摄像头,但是发现默认一直是前置摄像头,拍照很麻烦,于是找了很多文章,居然没有人提到,只好FQ去找 ...
- 尼康D90多点对焦
11点对焦 上市时间 2008 类型 单反数码相机 对焦方式 单区域AF:在选择区域内只对焦于目标可以从11个AF点传感器中的任意一个中选择 动态区域AF:对焦于选择区域的目标上,如果目标离开原来位置 ...
- Entity Framework基础
http://blog.csdn.net/hurtlingsnail/article/details/53113934