装饰模式定义
装饰模式是一种比较常见的模式,其定义如下:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
优点
- 装饰类和被装饰类可以独立发展,而不会相互耦合。Component类无须知道Decorator类,Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。
- 装饰模式是继承关系的一个替代方案。不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。
- 装饰模式可以动态地扩展一个实现类的功能。注意是动态。
-
装饰模式是对继承的有力补充。使用装饰模式可以实现易维护,易扩展,易复用等。在一些情况下使用继承就会增加很多子类,而且灵活性很差,当然维护也不容易了,也就是说装饰模式可以替代继承,解决我们类膨胀的问题。同时还有一个重要的区别,继承是静态地给类增加功能,而装饰模式是动态地增加功能。
注意:尽量减少装饰类的数量,以便降低系统的复杂度。
使用场景
- 需要扩展一个类的功能,或给一个类增加附加功能。
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
- 需要为一批的兄弟类进行改装或加装功能,首选装饰模式。
-
模式框架
装饰模式的通用类图如上图所示。
在类图中,有四个角色需要说明:
- Component抽象构件
Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象。
注:在装饰模式中,必然有一个最基本,最核心,最原始的接口或抽象类充当Component抽象构件。
- ConcreteComponent具体构件
ConcreteComponent是最核心,最原始,最基本的接口或抽象类的实现,要装饰的就是这个对象。
- Decorator装饰角色
一般是一个抽象类。实现接口或抽象方法,它里面可不一定有抽象的方法,在它的属性里必然有一个private变量指向Component抽象构件。
- 具体装饰角色
ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,你要把你最核心,最原始,最基本的东西装饰城其他东西。 -
代码:
/* * 抽象构件 */ public interface Component { public void operate(); } /* * 具体构件 */ public class ConcreteComponent implements Component{ //具体实现 public void operate() { // TODO Auto-generated method stub System.out.println("Do something"); } } /* * 抽象装饰者 */ public abstract class Decorator implements Component{ private Component component=null; //通过构造函数传递被修饰者 public Decorator(Component component){ this.component=component; } //委托给被修饰者执行 public void operate(){ this.component.operate(); } } /* * 具体装饰者1 */ public class ConcreteDecorator1 extends Decorator{ //定义被修饰者 调用父类的构造函数 public ConcreteDecorator1(Component component) { super(component); } //定义自己的修饰方法 private void method1(){ System.out.println("method1 修饰"); } //重写父类的Operation方法 @Override public void operate(){ this.method1(); super.operate(); } } /* * 具体装饰者2 */ public class ConcreteDecorator2 extends Decorator{ //定义被修饰者 调用父类的构造函数 public ConcreteDecorator2(Component component){ super(component); } //定义自己的修饰方法 private void method2(){ System.out.println("method2修饰"); } //重写父类的Operation方法 @Override public void operate(){ super.operate(); this.method2(); } } /* * 场景类 */ public class Client { public static void main(String[] args){ Component component=new ConcreteComponent(); //第一次修饰 component=new ConcreteDecorator1(component); //第二次修饰 component=new ConcreteDecorator2(component); //修饰后运行 component.operate(); } }
运行结果:
method1 修饰
Do something
method2修饰