一,装饰者模式
装饰者模式:
动态的将新功能附加到对象上,在功能扩展方面比继承更具有弹性,体现了OCP原则;
二,原理类图
意图: 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。
适用性:
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤消的职责。
- 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
三,实例
抽象类
package com.neei.decorator;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/7 16:23
* @Description: 游学网
* @throws:
*/
public abstract class Drink {
private String desc;
private double price = 0.0d;
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public abstract double cost();
}
缓存层
package com.neei.decorator.coffee;
import com.neei.decorator.Drink;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/7 16:25
* @Description: 游学网
* @throws:
*/
public class Coffee extends Drink {
@Override
public double cost() {
return super.getPrice();
}
}
被装饰物
package com.neei.decorator.coffee;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/7 16:29
* @Description: 游学网
* @throws:
*/
public class Latte extends Coffee {
public Latte() {
setDesc("拿铁咖啡");
setPrice(8D);
}
}
public class Civet extends Coffee {
public Civet() {
setDesc("猫屎咖啡");
setPrice(88D);
}
}
装饰者
package com.neei.decorator;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/7 16:31
* @Description: 游学网
* @throws:
*/
public class Decorator extends Drink {
private Drink drink;
public Decorator(Drink drink) {
this.drink = drink;
}
@Override
public double cost() {
return super.getPrice() + drink.cost();
}
//输出装饰者信息
@Override
public String getDesc() {
return super.getDesc() + ":" + super.getPrice() + "&&" + drink.getDesc() + ":" + drink.getPrice();
}
}
装饰物
package com.neei.decorator.season;
import com.neei.decorator.Decorator;
import com.neei.decorator.Drink;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/7 16:36
* @Description: 游学网
* @throws:
*/
public class Chocolate extends Decorator {
public Chocolate(Drink drink) {
super(drink);
setDesc("巧克力");
setPrice(3D);
}
}
public class Milk extends Decorator {
public Milk(Drink drink) {
super(drink);
setDesc("牛奶");
setPrice(2D);
}
}
public class Sugar extends Decorator {
public Sugar(Drink drink) {
super(drink);
setDesc("糖");
setPrice(1D);
}
}
调用
package com.neei.decorator;
import com.neei.decorator.coffee.Civet;
import com.neei.decorator.season.Chocolate;
import com.neei.decorator.season.Milk;
import com.neei.decorator.season.Sugar;
/**
* @param
* @Author: AaNeei
* @Date: 2019/10/7 16:39
* @Description: 游学网
* @throws:
*/
public class CoffeeBar {
public static void main(String[] args) {
//点一份猫屎,加糖,牛奶,巧克力各一份
Drink drink = new Civet();
System.out.println(drink.cost());
System.out.println(drink.getDesc());
//加糖
drink = new Sugar(drink);
System.out.println(drink.cost());
System.out.println(drink.getDesc());
//加牛奶
drink=new Milk(drink);
System.out.println(drink.cost());
System.out.println(drink.getDesc());
//加巧克力
drink=new Chocolate(drink);
System.out.println(drink.cost());
System.out.println(drink.getDesc());
}
}
四,源码分析
JDK源码中使用的装饰者模式,如FilterInputStream;
public class FilterInputStream extends InputStream {
/**
* The input stream to be filtered.
*/
protected volatile InputStream in;
...
}