装饰者模式
1、装饰者模式的动机
以客户端透明的方式以及,不需要创造更多子类的情况下,将对象的功能加以扩展,赋予类新的职责;
2、装饰者模式的定义
动态的将责任附加到新的对象上,若需要扩展功能时,装饰者提供了比继承更加具有弹性的替代方案;
3、装饰者模式的类结构图
模式分析:
-
与继承关系相比,关联关系的主要优势在于不会破坏类的封装性,而且继承是一种耦合度较大的静态关 系,无法在程序运行时动态扩展。
-
在软件开发阶段,关联关系虽然不会比继承关系减少编码量,但是到了软件维护阶段,由于关联关系使 系统具有较好的松耦合性,因此使得系统更加容易维护。当然,关联关系的缺点是比继承关系要创建更多 的对象。使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。
4、优缺点和适用场景
优点:
- 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
- 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为。
- 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。
- 可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
- 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。
缺点:
- 装饰者模式会产生许多的小对象和装饰者,装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度。
- 装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
适用场景:
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
- 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类: 第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是 因为类定义不能继承(如final类)
5、实例
例:饮料里面加入糖,奶等等其他作料;
饮料接口
/**
* Desc:饮料的公共接口
* ------------------------------------
* Author:XXXX
* Date:2017/9/1
* Time:17:28
*/
public interface Beverage {
String getDescription();
Double getPrice();
}
装饰者接口
public interface Decorator extends Beverage {}
Coffee基础组件
/**
* Desc:基础组件,原味Coffee
* ------------------------------------
* Author:XXXX
* Date:2017/9/1
* Time:17:36
*/
public class Coffee implements Beverage {
public String getDescription() {
return "coffee";
}
public Double getPrice() {
return 9.0;
}
}
糖装饰者
/**
* Desc:糖装饰者
* ------------------------------------
* Author:XXXX
* Date:2017/9/1
* Time:17:40
*/
public class SugarDecorator implements Beverage {
private Beverage beverage;
public SugarDecorator(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription()+" 加糖";
}
public Double getPrice() {
return beverage.getPrice()+2.3;
}
}
奶装饰者
/**
* Desc:奶装饰者
* ------------------------------------
* Author:XXXX
* Date:2017/9/1
* Time:17:45
*/
public class MilkDecorator implements Decorator {
private Beverage beverage;
public MilkDecorator(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription()+" 加奶";
}
public Double getPrice() {
return beverage.getPrice()+3;
}
}
测试类
/**
* Desc:
* ------------------------------------
* Author:XXXX
* Date:2017/9/1
* Time:17:46
*/
public class Test {
public static void main(String[] args) {
Beverage coffee = new Coffee();
//加糖Coffee
Beverage coffee1 = new SugarDecorator(coffee);
//即加糖,也加奶Coffee
Beverage coffee2 = new MilkDecorator(coffee1);
System.out.println(coffee2.getDescription());
System.out.println("价格:" + coffee2.getPrice());
}
}
- 上一篇 Java的Executor框架和线程池实现原理
- 下一篇 系统性能监控命令