[1] bugstack.cn/md/develop/…
[2] c.biancheng.net/view/1397.h…
[3] refactoringguru.cn/design-patt…
[4] cmsblogs.com/article/140…
[5] blog.csdn.net/lovelion
什么是装饰器模式场景装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
假设你正在开发一个提供通知功能的库, 其他程序可使用它向用户发送关于重要事件的通知。
最初的版本基于 Notifier 类,用来接受客户端消息参数并发送给一系列邮箱,邮箱列表通过构造函数传递。
后续有新的需求增加, 用户要求能够在手机短信、微信、QQ上接收消息,那么可以这样做,扩展通知类,在子类中加入额外的通知方法,然后组合多种通知方法即可解决问题
弊端- 系统扩展麻烦,在某些编程语言中无法实现,Java 中是不支持多继承的,所有每次要扩展一项功能,就必须新增一个类
- 代码重复,可以发现发送消息的代码在多个类中重复
- 系统庞大,类的数目非常多
根本原因在于,这个设计的复用机制不合理,上图采用的是继承复用的机制,而我们知道,根据设计原则,应该多用组合,少用继承。
- 继承是静态的。 你无法在运行时更改已有对象的行为, 只能使用由不同子类创建的对象来替代当前的整个对象。
- 子类只能有一个父类。 大部分编程语言不允许一个类同时继承多个类的行为。
因此我们可以换个角度,将 send 方法这个通知行为放在基类通知器中,将所有其他方法放入装饰中。
这样,客户端代码就可以以装饰器的模式封装自己想要的功能
装饰模式结构 结构1- 单个具体构件
- 没有抽象构件
如果只有一个具体构件而没有抽象构件时,可以让抽象装饰继承具体构件,也就是上面的 Notifier 的例子
结构2- 只有一个具体装饰
如果只有一个具体装饰时,可以将抽象装饰和具体装饰合并
结构3这个是经典的装饰器结构
- 有多个具体构件类
- 又有抽象构件类
- 部件,也叫抽象构件 (Component) 声明封装器和被封装对象的公用接口。
- 具体部件,也叫具体构件 (Concrete Component) 类是被封装对象所属的类。 它定义了基础行为, 但装饰类可以改变这些行为。
- 基础装饰 (base Decorator) 类拥有一个指向被封装对象的引用成员变量。 该变量的类型应当被声明为通用部件接口, 这样它就可以引用具体的部件和装饰。 装饰基类会将所有 *** 作委派给被封装的对象。
- 具体装饰类 (Concrete Decorators) 定义了可动态添加到部件的额外行为。 具体装饰类会重写装饰基类的方法, 并在调用父类方法之前或之后进行额外的行为。
- 客户端 (Client) 可以使用多层装饰来封装部件, 只要它能使用通用接口与所有对象互动即可。
装饰模式的核心在于抽象装饰类的设计,其典型代码如下所示:
class Decorator implements Component { //维持一个对抽象构件对象的引用 private Component component; //注入一个抽象构件类型的对象 public Decorator(Component component) { this.component=component; } public void operation( ) { component.operation( ); //调用原有业务方法 } } 复制代码
在抽象装饰类Decorator中定义了一个Component类型的对象component,维持一个对抽象构件对象的引用,并可以通过构造方法或Setter方法将一个Component类型的对象注入进来,同时由于Decorator类实现了抽象构件Component接口,因此需要实现在其中声明的业务方法operation(),需要注意的是在Decorator中并未真正实现operation()方法,而只是调用原有component对象的operation()方法,它没有真正实施装饰,而是提供一个统一的接口,将具体装饰过程交给子类完成。
在Decorator的子类即具体装饰类中将继承operation()方法并根据需要进行扩展,典型的具体装饰类代码如下:
class ConcreteDecorator extends Decorator { public ConcreteDecorator(Component component) { super(component); } public void operation() { super.operation(); //调用原有业务方法 addedBehavior(); //调用新增业务方法 } //新增业务方法 public void addedBehavior() { …… } } 复制代码
在具体装饰类中可以调用到抽象装饰类的operation()方法,同时可以定义新的业务方法,如 addedBehavior()
由于在抽象装饰类Decorator中注入的是Component类型的对象,因此我们可以将一个具体构件对象注入其中,再通过具体装饰类来进行装饰;此外,我们还可以将一个已经装饰过的Decorator子类的对象再注入其中进行多次装饰,从而对原有功能的多次扩展。
案例设计Sunny软件公司基于面向对象技术开发了一套图形界面构件库VisualComponent,该构件库提供了大量基本构件,如窗体、文本框、列表框等,由于在使用该构件库时,用户经常要求定制一些特效显示效果,如带滚动条的窗体、带黑色边框的文本框、既带滚动条又带黑色边框的列表框等等,因此经常需要对该构件库进行扩展以增强其功能
直接利用装饰器模式,进行系统设计,使系统具有更好的灵活性和扩展性
具体代码//抽象界面构件类:抽象构件类,为了突出与模式相关的核心代码,对原有控件代码进行了大量的简化 abstract class Component { public abstract void display(); } //窗体类:具体构件类 class Window extends Component { public void display() { System.out.println("显示窗体!"); } } //文本框类:具体构件类 class TextBox extends Component { public void display() { System.out.println("显示文本框!"); } } //列表框类:具体构件类 class ListBox extends Component { public void display() { System.out.println("显示列表框!"); } } //构件装饰类:抽象装饰类 class ComponentDecorator extends Component { private Component component; //维持对抽象构件类型对象的引用 //注入抽象构件类型的对象 public ComponentDecorator(Component component) { this.component = component; } public void display() { component.display(); } } //滚动条装饰类:具体装饰类 class ScrollBarDecorator extends ComponentDecorator { public ScrollBarDecorator(Component component) { super(component); } public void display() { this.setScrollBar(); super.display(); } public void setScrollBar() { System.out.println("为构件增加滚动条!"); } } //黑色边框装饰类:具体装饰类 class BlackBorderDecorator extends ComponentDecorator { public BlackBorderDecorator(Component component) { super(component); } public void display() { this.setBlackBorder(); super.display(); } public void setBlackBorder() { System.out.println("为构件增加黑色边框!"); } } 复制代码客户端代码
class Client{ public static void main(String args[]) { Component component,componentSB,componentBB; //全部使用抽象构件定义 component = new Window(); componentSB = new ScrollBarDecorator(component); //将装饰了一次之后的对象继续注入到另一个装饰类中,进行第二次装饰 componentBB = new BlackBorderDecorator(componentSB); componentBB.display(); } // 也可以这样写 Component component; component = new BlackBorderDecorator( new ScrollBarDecorator( new Window( ))); } 复制代码
装饰器模式在 Java 语言中的最著名的应用莫过于 Java I/O 标准库的设计了。例如,InputStream 的子类 FilterInputStream,OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。
BufferedReader in = new BufferedReader(new FileReader("filename.txt")); String s = in.readLine(); 复制代码小结
装饰器模式的主要优点有:
- 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
- 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
- 装饰器模式完全遵守开闭原则
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)