设计模式(5)-代理(Proxy)模式和装饰(Decorator)模式
来源:互联网 发布:离开雷锋的日子 知乎 编辑:程序博客网 时间:2024/06/16 19:19
代理模式和装饰模式总是让人混淆,他们形式上确实非常像。
代理模式
结构:
实现:
有这样一种场景,一种特别庞大的组件需要在特定的时候被绘制出来,这种庞大的组件绘制了之后会造成系统的负担。
此时可以使用代理模式,在确定这个组件必须被绘制的时候,才通过代理,将这个组件绘制出来。
class Component//普通组件{public: virtual void Draw();};class HugeComponent:public Component//特大组件{public: virtual void Draw();};class Proxy :public Component//代理{public: Proxy(Component*);//代理组件 //将对组件的绘制转接到维护的组件对象 virtual void Draw() { _componet->Draw(); };private: Component* _componet;};
装饰模式
结构:
实现:
有这样一种场景,一种组件需要被绘制出来,但是这种组件可能加上各种不同的元素,比如加个边框。
此时可以使用装饰者模式,用不同的装饰者类装饰这个组件后,再通过这些装饰者类的绘制就可以在绘制这个组件的基础上加上边框。
class Component//普通组件{public: Component(); virtual void Draw();};class Decorator :public Component//装饰者类{public: //装饰者一定要有被装饰对象 Decorator(Component* c) { _component = c; }; //将命令转交给被装饰对象 virtual void Draw() { _component->Draw(); };private: Component* _component;};class BorderDecorator :public Decorator//带边框装饰者{public: BorderDecorator(Component* c,float borderWidth) ; //不只是绘图,还要绘边框 virtual void Draw() { Decorator::Draw(); DrawBorder(_border); };private: void DrawBorder();//加边框 float _border;};void client(Component* component){ component->Draw();}void main(){ Component * com = new Component();//一个普通的组件 //用一个带边框的装饰者子类装饰 BorderDecorator *bd = new BorderDecorator(com,1.0f); client(bd);//客户调用带边框的装饰者}
差别
代理模式和装饰模式实在太像了,如果可以的话,代码都能写成一样,从形式上来区分是很难的。
但代理和装饰的实现目的是不一样的。
代理模式是将被代理类交给代理来管理,所以每一个代理维护一个被装饰对象。
装饰模式是用装饰类的基类维护一个对象,用装饰类的子类实现装饰,这就意味着,被装饰类并不受装饰者制,装饰者只能决定是自己是不是要装饰这个被装饰类,而无法决定被装饰者的行为。
这是他们最大的区别。
所以装饰模式如果没有装饰类的子类实现或者子类实现像代理一样,就蜕化为代理模式了
优点
装饰者模式有两个主要优点:
1.比多重继承灵活,装饰者类由于基类维护的是一个被装饰类基类,所以可以动态置换。
2.避免暴露被装饰者调用细节,装饰者子类只需要决定要不要为被装饰者添加装饰,而不能对被装饰者进行任何修改。
代理模式的优点主要有:
1.和装饰者一样,比多重继承灵活。
2.由于代理维护了一个对象引用,因此代理对这个对象拥有控制权,代理可以决定对象执行什么,不执行什么,这是与装饰者的不同。同时也是比装饰者灵活的地方。
思考
比起用装饰者或者代理这样的设计模式,实现同样的效果为什么不用回调呢?比如在代理的函数中传入函数指针,使用回调,不是比继承更方便吗?
事实上传函数指针这种方式确实更灵活,但不见得方便,本例中,只有一个函数实现了代理,如果有10个呢?难道要传10个指针?
但回调的优势也很明显,就是灵活,如以随意组合代理是其一,不用在代理内部维护一个引用是其二。
使用看习惯吧。没有特别需求的情况下使用代理这样的会更合适一些,因为指针类型自己维护不见得能保证正确,BUG会隐藏深一点儿。
- 设计模式(5)-代理(Proxy)模式和装饰(Decorator)模式
- 装饰模式(Decorator)和代理模式(Proxy)
- 我的设计模式-装饰(Decorator)、代理(Proxy)
- Java编程开发设计模式之--装饰者模式(Decorator)与代理模式(Proxy)
- [设计模式](六):装饰器模式(Decorator)和代理模式(Proxy)|委托模式(Delegater )
- 装饰器模式(Decorator)和代理模式(Proxy)
- 设计模式-装饰模式(Decorator Pattern)
- 设计模式---装饰模式(decorator)
- 设计模式 (十)装饰模式(Decorator)
- 设计模式 (十)装饰模式(Decorator)
- 设计模式 (十)装饰模式(Decorator)
- 【设计模式】之装饰模式(Decorator)
- 设计模式之装饰模式(Decorator)
- 设计模式之 装饰模式(Decorator)
- 设计模式之装饰模式(Decorator)
- Java设计模式---装饰模式(Decorator)
- 设计模式(五):装饰模式(Decorator)
- 设计模式(7)--Decorator 装饰模式
- stochastic matrix
- HDU-2020(绝对值排序)(abs函数)
- Linux学习~安装jdk
- Linux多进程-fork()
- Java Web 程序员的职业进阶之路
- 设计模式(5)-代理(Proxy)模式和装饰(Decorator)模式
- 后台小白:stuManager代码使用学习
- 何在 Android 程序中禁止屏幕旋转和重启Activity
- 正则化方法:L1和L2 regularization、数据集扩增、dropout
- AttributeError: module 'tensorflow.python.ops.nn' has no attribute 'seq2seq'
- 实现一个函数,可以左旋字符串中的k个字符
- 习题6.10
- Java程序设计(Java9版):第2章 数据类型与运算符(Data types and Operators)
- HDU1754线段树求取区间最大值