Decorator模式
我觉得这个模式有点绕。需要很仔细的来分清其中的继承关系。
Decorator模式的使用场景:当你要描述一个东西,比如说“人”这个东西,你回构建一个人的class,它包括很多人的属性,比如身高,体重,性别,年龄等等,你还有很多的施加于“人”上面的方法,比如吃饭,睡觉,跑步等等。但是,你可能希望给“人”添加一些额外的东西,就像游戏中的人物一样,他是带装备,比如“黄金盔甲”,“蓝宝石戒指
”,“青龙大刀”。并且,游戏中人物,你光出生的时候是啥装备都没有,随着你不断练级,你的装备才越来越多,你还可以丢掉一些落后的装备,这些装备都是在游戏中动态变化的,即它是在“运行时变化的”。你静下来想想,如何设计“人”这个class,如果使用继承,你显然是无法完成的(继承意味着你必须穷尽出所有可能的“人”的子类情况),这时候你必须使用组合。如何使用组合呢?这就是Decorator模式了。
设计的时候,有3个类,第一个为Component类,它是另外2个类的父类。从Component继承来ConcreteComponent类,这个类为具体类。从Component再继承来Decorator类,其中这个类拥有一个成员变量,为Component类对象的一个引用。
对于“人”的设计,Component就是抽象的People。ConcreteComponent就是具体的“人”,他包含有人的属性(身高,体重,性别。。)。对于Decorator,从它再继承出来具体的一些装备(“黄金盔甲”为一个ConcreteDecoratorA,“蓝宝石戒指”为ConcreteDecoratorB,而“青龙大刀”为 ConcreteDecoratorC,如果出现了一个新的装备,从Decorator再继承出来一个具体的装备类就行了)。在实际使用过程中,如果你只是使用一个“裸人”那么从ConcreteComponent就可以定义出来一个对象。之后你想给他添加“黄金盔甲”,这时候你就需要使用ConcreteDecoratorA定义出一个黄金盔甲的装备,那么人的属性是如何体现呢?我们知道Decorator拥有一个Component类对象的一个引用的成员变量,只要这个成员变量引用一个“人”,就是说在Decorator的构造函数就要去传入一个“Component”对象的引用。情况如下:
ConcreteComponent* pCom = new ConcreteComponent;
ConcreteDecoratorA* pDecA = new ConcreteDecoratorA(pCom);
从中可以看出,ConcreteDecoratorA本身就是描述了一个“人”(所以要从Component来继承),还是一个带有某种装备的“人”,人的属性表现在其包含了一个“人”对象的引用。再往下看:
ConcreteDecoratorB* pDecB = new ConcreteDecoratorB(pDecA);
由于pDecA本身就描述的是一个“人”,“黄金盔甲的人”也可以当成参数传入“蓝宝石戒指”,(这也说明Decorator要从Component继承过来),于是这个“蓝宝石戒指的人”,其人的属性表现在包含了一个“黄金盔甲的人”的引用(同时这个“黄金盔甲的人”它的人的属性是因为其包含一个“人”),如果看图的话,一个“带着蓝宝石戒指和黄金盔甲的人”的结构就是:
--------------------------
| 戒指 |
| ------------------ |
| | 盔甲 | |
| | ----------- | |
| | | 具体人 | | |
| | ------- --- | |
| ----------------- | |
---------------------------
在这里需要强调的是,ConcreteDecorator的对象就需要当成是一个component的对象,用上面的例子来说,虽然我们把装备称为“黄金盔甲”,但要晓得,程序中出现所有“黄金盔甲”的对象,都是表示““穿黄金盔甲的人””,而人的属性就是通过包含一个“xxx的人”的引用来传递。这就是为啥Decorator的父类就是component的原因。
我觉得这个模式有点绕。需要很仔细的来分清其中的继承关系。
Decorator模式的使用场景:当你要描述一个东西,比如说“人”这个东西,你回构建一个人的class,它包括很多人的属性,比如身高,体重,性别,年龄等等,你还有很多的施加于“人”上面的方法,比如吃饭,睡觉,跑步等等。但是,你可能希望给“人”添加一些额外的东西,就像游戏中的人物一样,他是带装备,比如“黄金盔甲”,“蓝宝石戒指
”,“青龙大刀”。并且,游戏中人物,你光出生的时候是啥装备都没有,随着你不断练级,你的装备才越来越多,你还可以丢掉一些落后的装备,这些装备都是在游戏中动态变化的,即它是在“运行时变化的”。你静下来想想,如何设计“人”这个class,如果使用继承,你显然是无法完成的(继承意味着你必须穷尽出所有可能的“人”的子类情况),这时候你必须使用组合。如何使用组合呢?这就是Decorator模式了。
设计的时候,有3个类,第一个为Component类,它是另外2个类的父类。从Component继承来ConcreteComponent类,这个类为具体类。从Component再继承来Decorator类,其中这个类拥有一个成员变量,为Component类对象的一个引用。
对于“人”的设计,Component就是抽象的People。ConcreteComponent就是具体的“人”,他包含有人的属性(身高,体重,性别。。)。对于Decorator,从它再继承出来具体的一些装备(“黄金盔甲”为一个ConcreteDecoratorA,“蓝宝石戒指”为ConcreteDecoratorB,而“青龙大刀”为 ConcreteDecoratorC,如果出现了一个新的装备,从Decorator再继承出来一个具体的装备类就行了)。在实际使用过程中,如果你只是使用一个“裸人”那么从ConcreteComponent就可以定义出来一个对象。之后你想给他添加“黄金盔甲”,这时候你就需要使用ConcreteDecoratorA定义出一个黄金盔甲的装备,那么人的属性是如何体现呢?我们知道Decorator拥有一个Component类对象的一个引用的成员变量,只要这个成员变量引用一个“人”,就是说在Decorator的构造函数就要去传入一个“Component”对象的引用。情况如下:
ConcreteComponent* pCom = new ConcreteComponent;
ConcreteDecoratorA* pDecA = new ConcreteDecoratorA(pCom);
从中可以看出,ConcreteDecoratorA本身就是描述了一个“人”(所以要从Component来继承),还是一个带有某种装备的“人”,人的属性表现在其包含了一个“人”对象的引用。再往下看:
ConcreteDecoratorB* pDecB = new ConcreteDecoratorB(pDecA);
由于pDecA本身就描述的是一个“人”,“黄金盔甲的人”也可以当成参数传入“蓝宝石戒指”,(这也说明Decorator要从Component继承过来),于是这个“蓝宝石戒指的人”,其人的属性表现在包含了一个“黄金盔甲的人”的引用(同时这个“黄金盔甲的人”它的人的属性是因为其包含一个“人”),如果看图的话,一个“带着蓝宝石戒指和黄金盔甲的人”的结构就是:
--------------------------
| 戒指 |
| ------------------ |
| | 盔甲 | |
| | ----------- | |
| | | 具体人 | | |
| | ------- --- | |
| ----------------- | |
---------------------------
在这里需要强调的是,ConcreteDecorator的对象就需要当成是一个component的对象,用上面的例子来说,虽然我们把装备称为“黄金盔甲”,但要晓得,程序中出现所有“黄金盔甲”的对象,都是表示““穿黄金盔甲的人””,而人的属性就是通过包含一个“xxx的人”的引用来传递。这就是为啥Decorator的父类就是component的原因。