通过C++和python场景实例理解装饰器设计模式。
来源:互联网 发布:chrome 插件 运行js 编辑:程序博客网 时间:2024/05/16 04:44
参考文章:(1)http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html (2)http://en.wikipedia.org/wiki/Decorator_pattern
装饰器是一个很著名的设计模式,充分利用了继承和聚合的优势,它以“装饰”的含义生动形象地描绘了“灵活、动态地为已经存在的对象添加额外的功能“的意图。
下面分别选取两个场景,并分别对应C++语言和python语言,帮助读者理解这个模式。
场景一:咖啡制作
C++代码示例:
#include <iostream>#include <string> /* Abstract base class */// The abstract Coffee class defines the functionality of Coffee implemented by decoratorstruct Coffee { virtual double getCost() = 0; // Returns the cost of the coffee virtual std::string getIngredients() = 0; // Returns the ingredients of the coffee virtual ~Coffee() = 0;};inline Coffee::~Coffee() { } /* SimpleCoffee class. */// Extension of a simple coffee without any extra ingredientsstruct SimpleCoffee : public Coffee { virtual double getCost() { return 1.0; } virtual std::string getIngredients() { return "Coffee"; }}; /* Decorators */// Decorator Milk that adds milk to coffee.struct MilkDecorator : Coffee { MilkDecorator (Coffee *basicCoffee) : basicCoffee(basicCoffee) { } virtual double getCost() { // Providing methods defined in the abstract superclass return basicCoffee->getCost() + 0.5; } virtual std::string getIngredients() { return basicCoffee->getIngredients() + ", " + "Milk"; }private: Coffee *basicCoffee;}; // Decorator Whip that adds whip to coffeestruct WhipDecorator : Coffee { WhipDecorator (Coffee *basicCoffee) : basicCoffee(basicCoffee) { } virtual double getCost() { return basicCoffee->getCost() + 0.7; } virtual std::string getIngredients() { return basicCoffee->getIngredients() + ", " + "Whip"; }private: Coffee *basicCoffee;}; /* Test program */int main() { SimpleCoffee s; std::cout << "Cost: " << s.getCost() << "; Ingredients: " << s.getIngredients() << std::endl; MilkDecorator m(&s); std::cout << "Cost: " << m.getCost() << "; Ingredients: " << m.getIngredients() << std::endl; WhipDecorator w(&s); std::cout << "Cost: " << w.getCost() << "; Ingredients: " << w.getIngredients() << std::endl; // Note that you can stack decorators: MilkDecorator m2(&w); std::cout << "Cost: " << m2.getCost() << "; Ingredients: " << m2.getIngredients() << std::endl;}
测试输出:
Cost: 1.0; Ingredients: CoffeeCost: 1.5; Ingredients: Coffee, MilkCost: 1.7; Ingredients: Coffee, WhipCost: 2.2; Ingredients: Coffee, Whip, Milk
场景二:为函数插入日志(Python)
在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。
decorator可以增强函数的功能,定义起来虽然有点复杂,但使用起来非常灵活和方便。
装饰器的定义很是抽象,我们来看一个小例子。
def foo(): print 'in foo()' foo()
这是一个很无聊的函数没错。但是突然有一个更无聊的人,我们称呼他为B君,说我想看看执行这个函数用了多长时间,好吧,那么我们可以这样做
import timedef foo(): start = time.clock() print 'in foo()' end = time.clock() print 'used:', end - start foo()
很好,功能看起来无懈可击。可是蛋疼的B君此刻突然不想看这个函数了,他对另一个叫foo2的函数产生了更浓厚的兴趣。
怎么办呢?如果把以上新增加的代码复制到foo2里,这就犯了大忌了~复制什么的难道不是最讨厌了么!而且,如果B君继续看了其他的函数呢?
使用如下装饰器模式可解决这个问题:#-*- coding: UTF-8 -*-import time def foo(): print 'in foo()' # 定义一个计时器,传入一个,并返回另一个附加了计时功能的方法def timeit(func): # 定义一个内嵌的包装函数,给传入的函数加上计时功能的包装 def wrapper(): start = time.clock() func() end =time.clock() print 'used:', end - start # 将包装后的函数返回 return wrapper foo = timeit(foo)foo()
我们只需要在定义foo以后调用foo之前,加上foo = timeit(foo),就可以达到计时的目的,这也就是装饰器的概念,看起来像是foo被timeit装饰了。在在这个例子中,函数进入和退出时需要计时,这被称为一个横切面(Aspect),这种编程方式被称为面向切面的编程(Aspect-Oriented Programming)。与传统编程习惯的从上往下执行方式相比较而言,像是在函数执行的流程中横向地插入了一段逻辑。在特定的业务领域里,能减少大量重复代码。
具体C++和python在对待装饰器上的不同,还请读者自行体会。
1 0
- 通过C++和python场景实例理解装饰器设计模式。
- 简单实例理解装饰者设计模式
- 理解设计模式之装饰器模式
- 装饰模式和python装饰器
- 更好的理解装饰设计模式和代理设计模式
- python设计模式之装饰器模式
- Python设计模式(八)【装饰器模式】
- Python设计模式-装饰器模式
- python设计模式之装饰器模式
- 【Python学习日记】【设计模式】装饰器(装饰模式)
- 设计模式---装饰模式 实例
- python 装饰器模式 我的理解
- Python装饰器 decorator 设计模式
- 装饰设计模式的理解。
- 装饰设计模式的理解
- 理解Python 返回函数和装饰器
- C语言和设计模式(装饰模式)
- C语言和设计模式(装饰模式)
- 【机器学习算法班】(一)管窥机器学习
- 一步一步写算法(之双向链表)
- Linux进程关系
- rabbitmq(4)
- codewarrior 警告C12056: SP debug info incorrect because of optimization or inline assembler
- 通过C++和python场景实例理解装饰器设计模式。
- Android中的xml、json格式数据解析
- chaussure air jordan pas cher 4MPpXsfLBqx7Ge6JJ3
- 《数字图像处理》——形态学图像处理
- 一步一步写算法(之循环单向链表)
- 针对自己的2014年总结
- Linux用户与“最小权限”原则
- C++利用gSoap调用WebService服务
- TCP/IP详解学习笔记(1)-基本概念