定义:动态地给一个对象添加一些额外的职责,就扩展功能而言,它比生成子类的方式更为灵活。
类图:
说明:Component表示抽象组件,它是定义对象的接口,可以给这些对象动态地增加职责(方法);ConcreteComponent表示具体组件,它定义具体的组件对象,装饰器可以给它增加额外的职责(方法);Decorator表示抽象装饰类,它维护一个指向抽象组件的执政,并定义一组与抽象组件接口一致的方法;ConcreteDecorator表示具体装饰类,它负责向组件添加新的职责。
优点:
①Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
②通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
缺点:
①这种比继承更加灵活机动的特性,也同时一位置更加多的复杂性。
②装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
③装饰模式使针对抽象组件(Component)类型的编程。但是,如果你要针对具体组件编程时,就应该重新考虑你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
适用环境:
①需要扩展一个类的功能,或给一个雷增加附加指责。
②需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
③需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
④当不能采用生成子类的方法扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为累定义被隐藏,或类定义不能用于生成子类。
实例场景:某系统需要提供一个文件加密模块,加密流程包括三个操作,分别是读取源文件、加密、保存加密后的文件。读取文件和保存文件使用流来实现,这三个操作相对独立,其业务代码封装在三个不同的类中。现在需要提供一个统一的加密外观类,用户可以直接使用该加密外观类完成文件的读取、加密和保存三个操作,而不需要与每一个类进行交互。
实例代码:
//抽象构件类:
/**
* 抽象窗体类:抽象构件类
* @author fly
*
*/
abstract class Window {
public abstract void display();
}
//简单构件
/**
* 简单窗体类:具体构件类
* @author fly
*
*/
class SimpleWindow extends Window{
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("显示窗体!");
}
}
//窗体装饰类
/**
* 窗体装饰类:抽象装饰类
* @author fly
*
*/
class WindowDecorator extends Window{
private Window window;
public WindowDecorator(Window window) {
// TODO Auto-generated constructor stub
this.window = window;
}
@Override
public void display() {
// TODO Auto-generated method stub
window.display();
}
}
/**
* 滚动条窗体装饰类:具体装饰者类
* @author fly
*
*/
class ScrollbarDecorator extends WindowDecorator{
public ScrollbarDecorator(Window window) {
// TODO Auto-generated constructor stub
super(window);
}
@Override
public void display() {
// TODO Auto-generated method stub
this.setScrollbar();
super.display();
}
public void setScrollbar(){
System.out.println("给窗体增加滚动条");
}
}
/**
* 滚动条窗体装饰类:具体装饰者类
* @author fly
*
*/
class TransparentDecorator extends WindowDecorator{
public TransparentDecorator(Window window) {
// TODO Auto-generated constructor stub
super(window);
}
@Override
public void display() {
// TODO Auto-generated method stub
this.setTransparent();
super.display();
}
public void setTransparent(){
System.out.println("将窗体设置为透明窗体!");
}
}
//客户端测试类
/**
* 客户端测试类
* @author fly
*
*/
class Client {
public static void main(String[] args) {
Window windowS,windowSB,windowT;
windowS = new SimpleWindow();
windowSB = new ScrollbarDecorator(windowS);
windowT = new TransparentDecorator(windowSB);
windowT.display();
}
}
//运行如下: