【设计模式】穿什么有这么重要? --- 装饰模式
一,定义
英文名字:Decorator Pattern,又称装饰者模式。
装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
二,总结
装饰模式什么时候实用?
当系统需要新功能的时候,向旧的类中添加新的代码,而新的代码装饰了原有类的核心职责或主要行为。
如果在主类中添加新的字段,新的方法和新的逻辑,从而增加了主类的复杂度。而这些新添加的类仅仅是满足特定情况的特殊需要。
解决方案:装饰模式,把每个要装饰的功能放在单独的类中,并让这个类包装它要装饰的对象,因此要执行特殊行为时,客户端可以在运行时候有顺序,有选择的装饰包装对象。
三,例子
取自大话设计模式,小菜穿衣服。根据所穿不同衣服,穿衣服的顺序分析一个人风格?内裤内穿是普通人,内裤外穿是超人。
1)小菜扮靓第一版
下面程序,通过控制台可以完成扮靓的基本衣服类型。
缺点:
如果要增加 “超人” 的装扮(内裤外穿),怎么办?
更改Person 类就违背了 开放 - 封闭原则,如何优化呢?把服饰写成子类,方便扩展衣物子类。
#include <iostream> using namespace std; class Person { private: string name; public: Person(string Iname)//最好和 name 区分(不要再采用name) { name = Iname; //name没有this } ~Person(){} void WearTShirts() { cout<<"t恤"<<endl; } void WearBigTrouser() { cout<<"垮裤"<<endl; } void WearSneakers() { cout<<"破球鞋"<<endl; } void WearSuit() { cout<<"西装"<<endl; } void WearTie() { cout<<"领带"<<endl; } void WearLeaterShoes() { cout<<"皮鞋"<<endl; } void show() { cout<<"装扮的"<<this->name<<endl; } }; int main() { Person xiaocai("小菜"); //没有new的创建对象方法 cout<<"第一种装扮"<<endl; xiaocai.WearTShirts(); xiaocai.WearBigTrouser(); xiaocai.WearSneakers(); xiaocai.show(); Person *daniu =new Person("大牛"); //没有new cout<<"第二种装扮"<<endl; daniu->WearSuit(); daniu->WearTie(); daniu->WearLeaterShoes(); daniu->show(); return 0; }
2)小菜扮靓第二版
改进:增加了Finery 服饰抽象类,和各种具体服饰子类,方便了扩展各种服饰子类,而不必更改Person类,符合开放--封闭原则。
缺点:要显示穿的什么,还得在客户端dtx.show() //显示t恤 , kk.show() //显示垮裤。相当于光着身子在大庭广众之下穿衣服,如何改进?
要内部组装完毕,然后显示出穿的什么来。这个貌似建造者模式(但是建造者模式要求建造过程是稳定的,这里可以内穿西装外套t恤)
#include <iostream> using namespace std; class Person { public: Person(string name) { m_Name = name; }; void Show(void) { cout << "装扮的"<< m_Name <<endl; }; private: string m_Name; }; class Finery//服饰抽象类 { public: virtual void Show(void) = 0; }; class TShirts :public Finery { public: void Show(void) { cout << "大T恤" <<endl; }; }; class BigTrouser :public Finery { public: void Show(void) { std::cout << "垮裤" <<endl; }; }; class Sneakers :public Finery { public: void Show(void) { cout << "破球鞋" <<endl; }; }; class Suit :public Finery { public: void Show(void) { cout << "西装" <<endl; }; }; class Tie :public Finery { public: void Show(void) { cout << "领带" <<endl; }; }; class LeatherShoe :public Finery { public: void Show(void) { cout << "皮鞋" << endl; }; }; int main() { Person* xiaocai = new Person("小菜"); Finery* dtx = new TShirts(); Finery* kk = new BigTrouser(); Finery* pqx = new Sneakers(); dtx->Show(); kk->Show(); pqx->Show(); xiaocai->Show(); return 0; }
3)小菜扮靓第三版
结构:Person类需要穿衣服,让抽象装饰类继承Person类。然后继承抽象服饰类,初始化服饰子类。
改进:相对于第二版,可以先将衣服穿好 (装饰过程)
Sneakers* pqx = new Sneakers();
BigTrouser* kk = new BigTrouser();
TShirts* dtx = new TShirts();pqx->Decorator(xiaocai);
kk->Decorator(pqx);
dtx->Decorator(kk);
然后再显示出来 dtx.show()
#include <string> #include <iostream> class Person { public: Person(std::string name) { m_name = name; }; virtual void Show(void) { std::cout << "装扮的" << m_name << std::endl; }; Person(){}; private: std::string m_name; }; //服饰类 class Finery :public Person { public: void Decorator(Person* comp) { this->m_pComponent = comp; }; void Show(void) { if (m_pComponent != NULL) { m_pComponent->Show(); } }; protected: Person* m_pComponent; }; //具体服饰类 class TShirts :public Finery { public: void Show(void) { std::cout << "大T恤" << std::endl; Finery::Show(); } }; class BigTrouser :public Finery { public: void Show(void) { std::cout << "垮裤" << std::endl; Finery::Show(); }; }; class Sneakers :public Finery { public: void Show(void) { std::cout << "破球鞋" << std::endl; Finery::Show(); }; }; class Suit :public Finery { public: void Show(void) { std::cout << "西装" << std::endl; Finery::Show(); }; }; class Tie :public Finery { public: void Show(void) { std::cout << "领带" << std::endl; Finery::Show(); }; }; class LeatherShoe :public Finery { public: void Show(void) { std::cout << "皮鞋" << std::endl; Finery::Show(); }; }; int main() { Person* xiaocai = new Person("小菜"); std::cout << "第一个装扮" << std::endl; Sneakers* pqx = new Sneakers(); BigTrouser* kk = new BigTrouser(); TShirts* dtx = new TShirts(); pqx->Decorator(xiaocai); kk->Decorator(pqx); dtx->Decorator(kk); dtx->Show(); std::cout << "第二个装扮" << std::endl; LeatherShoe* px = new LeatherShoe(); Tie* tie = new Tie(); Suit* suit = new Suit(); px->Decorator(xiaocai); tie->Decorator(px); suit->Decorator(tie); suit->Show(); return 0; }