为什么要修饰者模式
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案
uml

形式
- 修饰者和被修饰者对象有相同的超类型
- 可以用一个或者多个修饰者包装一个对象
- 修饰者和被修饰者有相同超类,那么可以在任何需要原始对象(被包装的)场合,用被包装过的对象代替它。
- 装饰者可以在委托给装饰者包装的行为(getDescription()、getCost())之前或者之后加上自己的行为,来达到特定的目的
代码
- 组件基类
public abstract class Component {
protected String description = null;
public String getDescription(){
return description;
}
public abstract double getCost();
}
- 子类实现类
public class ConcreteComponent1 extends Component{
public ConcreteComponent1(){
description = "ConcreteComponent1";
}
@Override
public double getCost() {
return 0.1;
}
}
- 修饰器基类
public abstract class Decorator extends Component{
public abstract String getDescription();
}
- 修饰器实现类
public class ConcreteDecorator1 extends Decorator{
private Component component;
ConcreteDecorator1(Component component){
this.component = component;
}
@Override
public String getDescription() {
return component.getDescription() + ",ConcreteDecorator1";
}
@Override
public double getCost() {
return component.getCost() + 1;
}
}
- 测试类
public class Test {
public static void main(String[] args) {
Component component = new ConcreteComponent1();
Component d1 = new ConcreteDecorator1(component);
Component d2 = new ConcreteDecorator2(d1);
System.out.println(d1.getDescription());
System.out.println(d2.getDescription());
System.out.println(d1.getCost());
System.out.println(d2.getCost());
}
}
结果:
ConcreteComponent1,ConcreteDecorator1
ConcreteComponent1,ConcreteDecorator1,ConcreteDecorator2
1.1
3.1
修饰者模式的优缺点
优点:
-
装饰者模式可以提供比继承更多的灵活性
-
可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
-
通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
-
具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。
缺点:
-
会产生很多的小对象,增加了系统的复杂性
-
这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
网友评论