在上传代码之前,先交代一下装饰模式的概念。。。
装饰模式(Decorator)可以在运行时动态地给对象增加功能。它也是对对象的包装,但与适配器模式不同的是它并没有改变被包装对象的接口,只是改变了它的能力范围,而且可以递归组合。
通过生成子类的方式也可以为对象增加功能,但它是静态的,而且大量的功能组合很容易产生“子类爆炸”现象。装饰模式可以动态、透明地给对象增加职责,并且在不需要的时候很容易去除,使用派生子类的方式无法达到这种灵活程度。
GOOD:当你向旧的类中添加新代码时,一般是为了添加核心职责或主要行为。而当需要加入的仅仅是一些特定情况下才会执行的特定的功能时(简单点就是不是核心应用的功能),就会增加类的复杂度。装饰模式就是把要添加的附加功能分别放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端就可以有选择地、按顺序地使用装饰功能包装对象。
下面是主要实现,参照Head First的星巴兹咖啡案例实现。
#pragma once #include <boost/format.hpp> #include <iostream> #include <string> using namespace std; class CBeverage { public: CBeverage(void); ~CBeverage(void); public: virtual int cost() = 0; virtual string getDescription() { return m_description; } virtual void setDescription(string strDescription) { m_description = strDescription; } protected: string m_description; }; class Blend: public CBeverage { public: int cost() { return 10; } }; class DarkRoast: public CBeverage { public: int cost() { return 12; } }; class Decorator: public CBeverage { public: //virtual string getDescription(); int cost() { return m_observed_->cost() + 0; } void setObserver(boost::shared_ptr<CBeverage> observed) { m_observed_ = observed; } protected: boost::shared_ptr<CBeverage> getobersver() { return m_observed_; } private: boost::shared_ptr<CBeverage> m_observed_; }; class Milk: public Decorator { public: string getDescription() { return getobersver()->getDescription() + ", Milk"; } int cost() { return getobersver()->cost() + 2;//milk price:2 } }; class Mocha: public Decorator { public: string getDescription() { return getobersver()->getDescription() + ", Mocha"; } int cost() { return getobersver()->cost() + 3;//mocha price: 3 } }; class Whip: public Decorator { public: string getDescription() { return getobersver()->getDescription() + ", Whip"; } int cost() { return getobersver()->cost() + 4;//whip price:4 } }; int _tmain(int argc, _TCHAR* argv[]) { boost::shared_ptr<CBeverage> blendObserved(new Blend); blendObserved->setDescription("blend coffee"); boost::shared_ptr<CBeverage> darkroastObers(new DarkRoast); darkroastObers->setDescription("DarkRoast coffee"); boost::shared_ptr<Decorator> blendwithmilk(new Milk); blendwithmilk->setObserver(blendObserved); boost::shared_ptr<Decorator> blendwithmocha(new Mocha); blendwithmocha->setObserver(blendObserved); boost::shared_ptr<Decorator> darkroastwithmocha(new Mocha); darkroastwithmocha->setObserver(darkroastObers); boost::shared_ptr<Decorator> blendwithmochawhip(new Whip); blendwithmochawhip->setObserver(blendwithmocha); boost::shared_ptr<Decorator> blendwithmochawhipmilk(new Milk); blendwithmochawhipmilk->setObserver(blendwithmochawhip); cout<<blendwithmilk->cost()<<endl; cout<<blendwithmilk->getDescription()<<endl; cout<<blendwithmocha->cost()<<endl; cout<<blendwithmocha->getDescription()<<endl; cout<<darkroastwithmocha->cost()<<endl; cout<<darkroastwithmocha->getDescription()<<endl; cout<<blendwithmochawhip->cost()<<endl; cout<<blendwithmochawhip->getDescription()<<endl; cout<<blendwithmochawhipmilk->cost()<<endl; cout<<blendwithmochawhipmilk->getDescription()<<endl; return 0; }