work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

设计模式-装饰者模式

Posted on 2018-10-07 14:54  work hard work smart  阅读(158)  评论(0编辑  收藏  举报

一、定义

定义:在不改变原有对象的基础上,将功能附加到对象上

提供了比继承更有弹性的替代方案(扩展原有对象功能)

类型: 结构型

 

二、使用场景

扩展一个类的功能或者给一个类添加附件职责

动态给一个对象添加功能,这些功能可以再动态的撤销

 

三、优点

继承的有力补充,比继承灵活,不改变原有对象的情况下给对象一个扩展功能

通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同的效果

符合开闭原则

 

四、缺点

会出现更多的代码,更多的类,增加程序的复杂性

动态装饰时,多层装饰时会更复杂

 

五、相关设计模式

1. 装饰者模式和代理模式

装饰者模式关注一个对象动态添加方法

代理模式关注控制对对象的访问

 

六、Coding

 1. 创建BatterCake 类

/**
 * 煎饼
 */
public class BatterCake {

    protected   String getDesc(){
        return  "煎饼";
    }

    protected  int cost(){
        return  8;
    }
}

  

2. 创建BatterCakeWithEgg

public class BatterCakeWithEgg  extends  BatterCake{
    @Override
    public String getDesc() {
        return super.getDesc() + " 加一个鸡蛋";
    }

    @Override
    public int cost() {
        return super.cost() + 1;
    }
}

  

3. 创建BatterCakeWithEggSausage类

public class BatterCakeWithEggSausage  extends  BatterCakeWithEgg{
    @Override
    public String getDesc() {
        return super.getDesc() + " 加一根香肠";
    }

    @Override
    public int cost() {
        return super.cost() + 2;
    }
}

  

4. 测试类

public class Test {
    public static void main(String[] args) {
        BatterCake batterCake = new BatterCake();
        System.out.println(batterCake.getDesc() + " 销售价格:" + batterCake.cost());

        BatterCakeWithEgg batterCakeWithEgg = new BatterCakeWithEgg();
        System.out.println(batterCakeWithEgg.getDesc() + " 销售价格:" + batterCakeWithEgg.cost());

        BatterCakeWithEggSausage batterCakeWithEggSausage = new BatterCakeWithEggSausage();
        System.out.println(batterCakeWithEggSausage.getDesc() + " 销售价格:" + batterCakeWithEggSausage.cost());
    }


}

缺点:不能增加个数,如需要两个鸡蛋和两个火腿肠

 

七、Coding(改进版本)

 1. 创建ABatterCake抽象类

public abstract class ABatterCake {
    protected  abstract String getDesc();

    protected  abstract int cost();
}

  

2. 创建BatterCake类  

public class BatterCake  extends  ABatterCake{
    @Override
    protected String getDesc() {
        return "煎饼";
    }

    @Override
    protected int cost() {
        return 8;
    }
}

  

3. 创建AbstractDecorator。 这里可以不用抽象类

public abstract class AbstractDecorator extends ABatterCake {

    private  ABatterCake aBatterCake;

    public  AbstractDecorator(ABatterCake aBatterCake){
        this.aBatterCake = aBatterCake;
    }

    protected abstract  void doSomething();

    @Override
    protected String getDesc() {
        return this.aBatterCake.getDesc();
    }

    @Override
    protected int cost() {
        return this.aBatterCake.cost();
    }
}

  

4. 创建装饰类 EggDecorator  

public class EggDecorator  extends  AbstractDecorator{
    public EggDecorator(ABatterCake aBatterCake) {
        super(aBatterCake);
    }

    @Override
    protected void doSomething() {

    }

    @Override
    protected String getDesc() {
        return super.getDesc() + " 加一个鸡蛋";
    }

    @Override
    protected int cost() {
        return super.cost() + 1;
    }
}

 

5. 创建装饰类

public class SausageDecorator  extends  AbstractDecorator{

    public SausageDecorator(ABatterCake aBatterCake) {
        super(aBatterCake);
    }

    @Override
    protected void doSomething() {

    }

    @Override
    protected String getDesc() {
        return super.getDesc() + "加一根香肠";
    }

    @Override
    protected int cost() {
        return super.cost() + 2;
    }
}

  

6. 创建测试类

public class Test {

    public static void main(String[] args) {
        ABatterCake aBatterCake = new BatterCake();
        aBatterCake = new EggDecorator(aBatterCake);
        aBatterCake = new EggDecorator(aBatterCake);
        aBatterCake = new EggDecorator(aBatterCake);
        System.out.println(aBatterCake.getDesc() + " 销售价格:" + aBatterCake.cost());



    }
}

  

7. UML图

 

 

八、装饰者模式在源码中的应用

 1.java.io包下的BufferedReader类

继承于Reader抽象类。BufferedReader的构造器如下

    public BufferedReader(Reader var1, int var2) {
        super(var1);
        this.markedChar = -1;
        this.readAheadLimit = 0;
        this.skipLF = false;
        this.markedSkipLF = false;
        if(var2 <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        } else {
            this.in = var1;
            this.cb = new char[var2];
            this.nextChar = this.nChars = 0;
        }
    }

  

2. BufferedOutputStream和BufferedInputStream

BufferedOutputStream继承自FilterOutputStream, FilterOutputStream继承自OutputStream

BufferedOutputStream的构造器

    public BufferedOutputStream(OutputStream var1, int var2) {
        super(var1);
        if(var2 <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        } else {
            this.buf = new byte[var2];
        }
    }

  

 3. FilterInputStream是一个装饰者,LineInputStream,BufferedInputStream,DataInputStream是实际的装饰者。

 

4. 在spring中的TransactionAwareCacheDecorator类

public class TransactionAwareCacheDecorator implements Cache {
    private final Cache targetCache;

    public TransactionAwareCacheDecorator(Cache targetCache) {
        Assert.notNull(targetCache, "Target Cache must not be null");
        this.targetCache = targetCache;
    }
}

  

5. Mybatis中的org.apache.ibatis.cache.Cache类

例如FifoCache 类

public class FifoCache implements Cache {
    private final Cache delegate;
    private Deque<Object> keyList;
    private int size;

    public FifoCache(Cache delegate) {
        this.delegate = delegate;
        this.keyList = new LinkedList();
        this.size = 1024;
    }
}