java设计模式-装饰模式

文章来源:https://blog.csdn.net/a2572371/article/details/78142589
本次直接应用经典案列
我对装饰模式深刻理解:比如下面列子中,首先默认是白开水组件,然后动态扩展了绿茶和红茶组件(基于基础方法hasMaterial和cost方法),

定义:装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

1,不改变原类文件。

2,不使用继承。

3,动态扩展。


装饰者模式中的4个角色

  (1)被装饰者抽象Component:是一个接口或者抽象类,定义最核心的对象,这个类是装饰者的基类,例如Tea接口

  (2)被装饰者具体实现ConcreteComponent:这是Component接口或抽象类的实现,例如本例中的SuperTea

  (3)装饰者Decorator:一般是抽象类,实现Component,它里面必然有一个指向Component的引用,例如本例中AbstractTea

  (4)装饰者实现ConcreteDecorator1和ConcreteDecorator2:用来装饰最基本的类,如本例中的RedTea

example

被装饰抽象:

/**
 * Description:茶的基类(组件)
 * User: lc
 * Date: 2017/9/29 0029
 * Time: 下午 1:28
 */
public interface Tea {
    /**
     * 成分
     */
    String hasMaterial();
    /**
     * 价格
     *
     * @return
     */
    BigDecimal cost();
}

被装饰者具体实现:
/**
 * Description:茶的鼻祖实现(主实现)
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 1:07
 */
public class SuperTea implements Tea {
    @Override
    public String hasMaterial() {
        return "白开水";
    }
    @Override
    public BigDecimal cost() {
        return BigDecimal.ONE;
    }
}
装饰者:

/**
 * Description:抽象组件
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 1:10
 */
public abstract class AbstractTea implements Tea {
    private Tea tea;
    public AbstractTea(Tea tea) {
        this.tea = tea;
    }
    public String hasMaterial() {
        return this.tea.hasMaterial();
    }
    ;
    public BigDecimal cost() {
        return this.tea.cost();
    }
}

装饰者实现:

/**
 * Description:红茶
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 1:14
 */
public class ReadTea extends AbstractTea {
    public ReadTea(Tea tea) {
        super(tea);
    }
    /**
     * 返回红茶组成成分
     *
     * @return
     */
    @Override
    public String hasMaterial() {
        return "red茶叶、" + super.hasMaterial();
    }
    /**
     * 返回红茶的价格
     *
     * @return
     */
    @Override
    public BigDecimal cost() {
        return new BigDecimal(3.0).add(super.cost());
    }
}
装饰者实现:

/**
 * Description:绿茶
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 1:28
 */
public class GreenTea extends AbstractTea {
    public GreenTea(Tea tea) {
        super(tea);
    }
    /**
     * 返回绿茶组成成分
     *
     * @return
     */
    @Override
    public String hasMaterial() {
        return "green茶叶、" + super.hasMaterial();
    }
    /**
     * 返回绿茶的价格
     *
     * @return
     */
    @Override
    public BigDecimal cost() {
        return new BigDecimal(4.0).add(super.cost());
    }
}
测试:

/**
 * Description:
 * User: lc
 * Date: 2017/9/30 0030
 * Time: 下午 1:30
 */
public class Test {
    public static void main(String[] args) {
        System.out.println("客官:老板来一杯茶。。。。。。");
        Tea superTea=new SuperTea();
        System.out.println("老板:好嘞,客官。茶成分:"+superTea.hasMaterial()+"--价格:"+superTea.cost()+"元");
        System.out.println("客官:老板茶没味道。来杯红茶");
        AbstractTea abstractTea=null;
        abstractTea=new ReadTea(superTea);
        System.out.println("老板:好嘞,客官。红茶成分:"+abstractTea.hasMaterial()+"--价格:"+abstractTea.cost()+"元");
        System.out.println("客官:老板有么有别的茶?");
        System.out.println("老板:还有绿茶?");
        abstractTea=new GreenTea(superTea);
        System.out.println("老板:好嘞,客官。绿茶成分:"+abstractTea.hasMaterial()+"--价格:"+abstractTea.cost()+"元");
        System.out.println("客官:老板有没有绿红茶?");
        System.out.println("老板:你确定要?");
        abstractTea=new ReadTea(abstractTea);
        System.out.println("老板:好嘞,客官。绿红茶成分:"+abstractTea.hasMaterial()+"--价格:"+abstractTea.cost()+"元");
    }
}

结果:

客官:老板来一杯茶。。。。。。
老板:好嘞,客官。茶成分:白开水--价格:1元
客官:老板茶没味道。来杯红茶
老板:好嘞,客官。红茶成分:red茶叶、白开水--价格:4元
客官:老板有么有别的茶?
老板:还有绿茶?
老板:好嘞,客官。绿茶成分:green茶叶、白开水--价格:5元
客官:老板有没有绿红茶?
老板:你确定要?
老板:好嘞,客官。绿红茶成分:red茶叶、green茶叶、白开水--价格:8元

  

总结:

聪明的你,可能已经发现 就2个装饰者实现类,但是老板可以制定出3种茶。就我自己的理解 装饰者模式:就是修饰某个组件。比如本文章的例子Tea/superTea 是主题,而abstractTea以及具体的实现都是,封装了一些的装饰物品。比如随着老板生意越做越好,可能会添加很多种茶,甚至在原有的茶基础上添加一些配料。比如说红茶 (以后可能会出大杯、中杯、小杯等)。


结论:

1.装饰者类要实现真实类同样的接口(abstractTea实现Tea)

2.装饰者类内有一个真实对象的引用(可以通过装饰者类的构造器传入)(abstractTea引用了Tea)

3.装饰类对象在主类中接受请求,将请求发送给真实的对象(相当于已经将引用传递到了装饰类的真实对象)

4.装饰者可以在传入真实对象后,增加一些附加功能(因为装饰对象和真实对象都有同样的方法,装饰对象可以添加一定操作在调用真实对象的方法,或者先调用真实对象的方法,再

添加自己的方法)

5.不用继承,


优点:

 复用现有的代码(红绿茶就复用了绿茶以及红茶的代码),增强原有的组件的功能


缺点:

1.衍生出一些列的小对象,导致错中复杂


现成例子:JDK中的装饰者模式

 java.io中很多使用了装饰者模式
举个例子:FilterInputStream继承(实现)了InputStream,同时,BufferedInputStream继承了FilterInputStream,
1,被装饰者抽象组件:即最顶层的基类InputStream
2.被装饰者具体实现ConcreteComponent:FileInputStream和FileOutputStream就是它的实现
3.装饰者Decorator:FilterInputStream中有一个InputStream的实例和构造方法传入InputStream对象
    protected volatile InputStream in;  
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }  
4.装饰者实现:在   BufferedInputStream  中有构造方法传入InputStream对象,实现了装饰
    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }  


 
 

猜你喜欢

转载自blog.csdn.net/qq_39291929/article/details/80871492