女人常说男人喜新厌旧。仅仅见新人笑,那闻旧人哭,但装饰模式(Decorator)却是一种结交新朋友不忘老朋友的设计模式,很适合去古代当老公(现代是不行的。由于仅仅能娶一个老婆了)。装饰模式的本质是每个装饰对象都被保留一个被其装饰的对象,装饰对象在展示新功能时会同一时候去调用被其装饰的对象的同功能函数,通过如此层层包括调用(即装饰)。形成一个类似链表的结构。接下来的介绍中,我们还会看到很多其它的类似链表结构的设计模式,比方职责链模式、状态模式。
仍以《大话设计模式》一书中装饰模式的小菜穿衣的样例为例。来看看装饰模式是怎样做到家里红旗不倒,外面彩旗飘飘的。小菜要去会妹子。临行前为了给妹子留个好印象。精选牛仔裤一条。然后搭上简约风T恤,装扮一新后出门。为了可以让小菜搭配不论什么衣服。使用装饰模式描写叙述这一过程。
1、穿衣基类。仅仅有一个函数Show(),显示穿的衣服
装饰模式适合在原有功能上添加了新功能,可是新功能被调用前/后仍须要调用原有功能的情况,特别适合功能一层一层的扩展,同一时候保持旧有功能的正常调用的场景。
仍以《大话设计模式》一书中装饰模式的小菜穿衣的样例为例。来看看装饰模式是怎样做到家里红旗不倒,外面彩旗飘飘的。小菜要去会妹子。临行前为了给妹子留个好印象。精选牛仔裤一条。然后搭上简约风T恤,装扮一新后出门。为了可以让小菜搭配不论什么衣服。使用装饰模式描写叙述这一过程。
1、穿衣基类。仅仅有一个函数Show(),显示穿的衣服
class CDress { public: virtual ~CDress() {} virtual void Show() { printf("dressed boy. "); } };2、装饰类基类
class CFinery : public CDress { public: CFinery() : m_poDress(NULL) {} virtual ~CFinery() {} virtual void Show() { if (m_poDress) { m_poDress->Show(); } } void Decorate(CDress* poCDress) { m_poDress = poCDress; } private: CDress* m_poDress; };3、T恤和牛仔裤的详细装饰类
class CTShirt : public CFinery { public: virtual ~CTShirt() {} void Show() { printf("Tshirt "); CFinery::Show(); } }; class CJeans : public CFinery { public: virtual ~CJeans() {} void Show() { printf("Jeans "); CFinery::Show(); } };
这里需注意,装饰类对象的Show()函数在显示出本对象的装扮的同一时候,须要去调用装饰基类的Show()函数,以显示其被装饰对象的旧有装扮。即不能忘了老朋友。
4、装饰过程int main(int argc, char* argv[]) { CDress oCDress; CTShirt oCTShirt; CJeans oCJeans; oCTShirt.Decorate(&oCDress); oCJeans.Decorate(&oCTShirt); oCJeans.Show(); return 0; }
通过装饰过程能够看出,oCJeans 对象装饰了 oCTShirt 对象。所以 oCJeans 调用 Show() 函数时会调用 oCTShirt 的 Show() 函数,oCTShirt 又装饰了 oCDress 对象。这时 oCTShirt 又会调用 oCDress 的 Show() 函数。有点类似递归,也有点类似链表的味道,当然我们知道递归须要有一个终结者的。不然就没完没了了,所以最后被装饰的对象 oCDress 是不在有不论什么装饰对象的。
同一时候,假设小菜的妹子不喜欢这套打扮风格了,说要小菜把T恤换成衬衫,这时我们仅仅要新增一个衬衫装饰类 CShirt ,然后把 oCJeans 的装饰对象换成 CShirt 就可以。这里可见,使用了装饰模式后,换衣服都方便灵活多了。
5、装饰模式的应用装饰模式适合在原有功能上添加了新功能,可是新功能被调用前/后仍须要调用原有功能的情况,特别适合功能一层一层的扩展,同一时候保持旧有功能的正常调用的场景。
比方我们设计一个编辑框的控件类,最初仅仅有编辑文字的功能,我们新增一个装饰类后,我们能编辑出彩色的文字,这时我们仅仅须要设置控件的背景颜色,然后去调用旧的对象编辑文字功能就可以。过一段时间老大提新要求了,要求这个编辑框控件要搞和谐社会,要屏蔽敏感词,这时我们再新增一个装饰类。添加建设和谐社会功能后,再去调用编辑彩色文字的装饰类。当然,我们还能灵活变动,搞和谐社会的装饰类为了不花哨,也能够直接装饰原来的编辑框控件类。抛弃中间搞彩色文字的过程。