浅谈装饰者模式

装饰者-定义与类型

  • 定义:在不改变变原先对象的基础上,将功能附加到对象上。
  • 提供了比继承更加有弹性的替换方法(扩展原先对象的功能)
  • 他的类型:结构型

装饰者的适用场景

  • 扩展一个类的功能或者给一个类添加附加的职责
  • 动态的给一个对象添加功能,这些功能可以动态的撤销。

装饰者模式的优点与不足

优点:

继承的有力补充,比继承更加灵活,不改变原有对象的基础上给一个对象扩展功能。
通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同的效果。
符合开闭原则

缺点:

会出现更多的代码,更多的类,增加了程序复杂性。
动态装饰者时,多层装饰时复杂。

写一个装饰者的demo,例如做一个蛋糕,刚开始我们不知道要做什么样的蛋糕,所以呢,先把它搞成抽象的,这个抽象的蛋糕类有描述和价格;然后创建一个真正的原生蛋糕类,继承抽象蛋糕;现在被装饰的蛋糕已经建好了,接下来我们开始设计装饰蛋糕的装饰类;这里写了两个装饰蛋糕的装饰类,分别是草莓蛋糕和巧克力蛋糕,他们都继承自抽象的装饰类,这时这几个类的UML图如下所示:
在这里插入图片描述

抽象蛋糕类

public abstract class AbstractCake {
    protected abstract int cost;
    protected abstract String desc;

原生蛋糕类

public class Cake extends AbstractCake {

    @Override
    public int getCost() {
        return 10;
    }

    @Override
    public String getDesc() {
        return "一个原生蛋糕";
    }
}

抽象装饰类

public abstract class BaseDecorate extends AbstractCake {
    private AbstractCake abstractCake;

    public BaseDecorate(AbstractCake abstractCake) {
        this.abstractCake = abstractCake;
    }

    @Override
    public int getCost() {
        return this.abstractCake.getCost();
    }

    @Override
    public String getDesc() {
        return this.abstractCake.getDesc();
    }
}

草莓装饰类

/**
 * 草莓装饰蛋糕
 */
public class CakeWithStrawberry extends BaseDecorate {


    public CakeWithStrawberry(AbstractCake abstractCake) {
        super(abstractCake);
    }

    @Override
    public int getCost() {
        return super.getCost()+15;
    }

    @Override
    public String getDesc() {
        return super.getDesc()+"  加了草莓";
    }
}

巧克力装饰蛋糕

package decorate;

/**
 * 巧克力装饰蛋糕
 */
public class CakeWithChocolate extends BaseDecorate {
    public CakeWithChocolate(AbstractCake abstractCake) {
        super(abstractCake);
    }

    @Override
    public int getCost() {
        return super.getCost()+20;
    }

    @Override
    public String getDesc() {
        return super.getDesc()+"  加了巧克力";
    }
}

关于在java中装饰者模式的使用有哪些?
emm,首先IO中的大部分类都能看到装饰者的身影,比如,BufferedReader,BufferedWriter…
就拿BufferedReader举例:
首先BufferedReader的继承树。
在这里插入图片描述
他的父类是字符输入流Reader,然后看第一个私有属性字段就是Reader,

public class BufferedReader extends Reader {

    private Reader in;
	//.....
	//构造方法
	public BufferedReader(Reader in, int sz) {
        super(in);
        if (sz <= 0)
            throw new IllegalArgumentException("Buffer size <= 0");
        this.in = in;
        cb = new char[sz];
        nextChar = nChars = 0;
    }

他的这个构造方法的主要作用就是创建一个字符输入流,并且可以指定缓冲区的大小,而原本他老爹,不对,他父类的构造方法中就是创建了一个字符读取流,也就是reader,

Reader类:
protected Reader(Object lock) {
        if (lock == null) {
            throw new NullPointerException();
        }
        this.lock = lock;
    }

这里他只是在原先基础上加了点佐料也就是在创建的时候设置缓冲的大小。所以这里的装饰者就是BufferedReader,他老爹Reader就是被装饰的。

以上就是本人对装饰者模式的一些理解,如果有哪些不对的地方,欢迎指出,共同学习!

付出不一定有回报,但不付出一定没有!

posted @ 2020-03-20 21:10  起个名字都这么男  阅读(95)  评论(0编辑  收藏  举报