与访问者模式类似的做法,区别是访问者的访问人数和类型 以及 要对被访问者做的事情 与装饰者不同。
相同点:它们都拥有第三方(被访问者/被装饰者)通过聚合形式参与到(访问者/装饰者)进来
不同点:
1. 被装饰者只允许一个进入装饰者类,而被访问者可以有多个进入访问者类;
2. 装饰者与被装饰者的基类相同(同一类群),而访问者与被访问者的基类不相同(非同一类群)
3. 装饰者必定会调用被装饰者的功能,在此前提下进行附加其他功能,而访问者是没有此条约束的。
举例说明:
原有类Sphere(绘图圆形类)继承于IShape接口,IShape内有Draw()接口方法,Sphere实现Draw接口方法。
在Sphere已经编写好代码之后,突然有一天策划心血来潮说,绘图圆形之后能不能再画出一个矩形包囊住画出来的圆形?
如果不破坏原有类Sphere内部的情况下,你需要再创一个类似Sphere的类,完全重写它的功能来实现策划的需求。
如果策划想在上面所说的需求上再加个在圆形中间画个等边三角形,那又得新创一个类,完全重写它的功能,此时发现只要策划每次要在某个基础上新增功能时,我们就得新建一个类,当需求越来越多时,类也会随之变多,项目就越发难以维护。
此时就需要装饰模式来解决这个问题,在原有类Sphere的功能基础上,附加新的功能(画个矩形包囊圆形)。
那就是新建一个装饰器SphereDecorator 继承于IShape,内有IShape sphere成员,实现Draw接口方法;
Draw接口方法如下:
void Draw(){
sphere.Draw();
//TODO画个矩形包囊圆形(新功能)
}
外部用法:
SphereDecorator sphereDecorator = new SphereDecorator()
Sphere sphere = new Sphere()
sphereDecorator.SetSphere(sphere);
sphereDecorator.Draw();
面对策划在(圆形外加个矩形)基础上,再新增画个三角形在圆形内部的需求,我们只需修改SphereDecorator的Draw即可
void Draw(){
sphere.Draw();
//TODO画个矩形包囊圆形(新功能1)
//TODO在圆形内画个三角形(新功能2)
}