设计模式之装饰者模式
装饰者模式(Decorator)
1.基本介绍
- 动态的将新功能附加到对象上,在功能扩展方面,它比继承更有弹性,体现了开闭原则
2.原理
1.原理类图
2.分析
装饰者模式就像是打包一个快递,要寄送的物品为主体,即被装饰类,包装即为装饰类,对主体进行包装
- Component :被装饰的主体
- ConcreteComponent:被装饰的具体的主体
- Decorator:装饰者
- 在Component 和ConcreteComponent之间还可以设计一个缓冲层,创建一个公共类抽象出各个ConcreteComponent的公共特点
3.案例
装饰者模式实现类图
角色分析
- Drink是装饰者的抽象类,Component
- ShortBlack就是单品咖啡
- Decortor是一个装饰类,含有一个被装饰的对象(Drink obj)
- Decortor的cost方法进行一个费用的叠加计算,递归的计算价格
代码实现
Drink类
public abstract class Drink {
public String des;
private float price = 0.0f;
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
//计算费用的抽象方法
//子类来实现
public abstract float cost();
}
抽取单品咖啡公共的部分
public class Coffee extends Drink{
@Override
public float cost() {
// TODO Auto-generated method stub
return getPrice();
}
}
单品类的实现
public class LongBlack extends Coffee{
public LongBlack() {
setDes("LongBlack");
setPrice(18.0f);
}
}
装饰类Decortor
public class Decorator extends Drink{
private Drink obj;
public Decorator(Drink obj) {
super();
this.obj = obj;
}
@Override
public float cost() {
// TODO Auto-generated method stub
return obj.cost() + super.getPrice();
}
@Override
public String getDes() {
// TODO Auto-generated method stub
return super.getDes()+""+getPrice()+"&&"+obj.getDes();
}
}
具体的调味品:组合了一个单品的咖啡
//具体的Chocolate,这里就是调味品
public class Chocolate extends Decorator{
public Chocolate(Drink obj) {
super(obj);
// TODO Auto-generated constructor stub
setDes("巧克力");
setPrice(3.0f); //调味品的价格
}
}
4.IO源码分析
结构图
分析
InputStream是一个抽象类,他具有多个子类(具体的主体,例如FileInputStream),属于装饰者模式中的主体角色,其中定义了许多抽象方法由子类来实现
public abstract class InputStream implements Closeable {
InputStream的子类FileInputStream,充当具体的主体类
public
class FileInputStream extends InputStream
{
FilterInputStream装饰者类,继承了InputStream,组合了一个InputStream,符合我们上述讲的装饰者角色
public
class FilterInputStream extends InputStream {
/**
* The input stream to be filtered.
*/
protected volatile InputStream in;
而FilterInputStream的子类对InputStream进行了组合赋值,充当的是上述例子调味品的角色
public
class DataInputStream extends FilterInputStream implements DataInput {
/**
* Creates a DataInputStream that uses the specified
* underlying InputStream.
*
* @param in the specified input stream
*/
public DataInputStream(InputStream in) {
super(in);
}
如上介绍的模式在我们应用的时候则是这样的
//创建一个包含了主体InputStream的装饰类,将主体单品传入构造器,获得一个经过包装的FileInputStream对象,此时已经是DataInputStream对象了
DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file));