当前位置: 移动技术网 > IT编程>软件设计>设计模式 > 结合JDK源码看设计模式——装饰者模式

结合JDK源码看设计模式——装饰者模式

2019年04月06日  | 移动技术网IT编程  | 我要评论

定义

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

适用场景

  1. 扩展一个类的功能
  2. 动态的给对象增加功能,当功能不需要的时候能够动态删除

详解

  在看到定义的时候,可能很多人会想,这不就是继承吗?的确很像,不过是比继承更加有弹性的替代方案。就像原型模式和new之间的关系一样,有区别,但是区别又不是特别大。装饰者一个很重要的词就是动态,他可以灵活的选择要这个功能还是不要。在装饰者中要有四个角色:抽象的实体类,具体的实体类,抽象的装饰者,具体的装饰者。下面画一个大致的uml图

  实体类创建之后,如果想扩展实体类那么一般的想法是继承,当然继承也是其中方法之一。上面由uml图就可以看出,在装饰者模式下,我们可以通过装饰类下的扩展功能实现对抽象实体类的包装。当我们需要扩展功能就多加一个扩展功能,不需要扩展功能就不用添加,是一个很动态的扩展方式。下面具体看代码解析。

抽象实体类

public abstract class abstractcake {
    protected abstract string getcake();
    protected abstract int cost();

}

实体类

public class cake extends abstractcake{
    @override
    protected string getcake() {
        return "蛋糕";
    }

    @override
    protected int cost() {
        return 100;
    }
}

抽象装饰类(可以抽象也可以不抽象)

public class abstractdecorator extends abstractcake {
    private abstractcake abstractcake;

    public abstractdecorator(abstractcake abstractcake) {
        this.abstractcake = abstractcake;
    }



    @override
    protected string getcake() {
        return this.abstractcake.getcake();
    }

    @override
    protected int cost() {
        return this.abstractcake.cost();
    }
}

扩展功能1

public class fruitdecorator extends abstractdecorator {
    public fruitdecorator(abstractcake abstractcake) {
        super(abstractcake);
    }



    @override
    protected string getcake() {
        return super.getcake()+" 加一层水果";
    }

    @override
    protected int cost() {
        return super.cost()+20;
    }
}

扩展功能2

public class sugerdecorator extends abstractdecorator{
    public sugerdecorator(abstractcake abstractcake) {
        super(abstractcake);
    }



    @override
    protected string getcake() {
        return super.getcake()+" 多加糖";
    }

    @override
    protected int cost() {
        return super.cost()+10;
    }
}

测试类

public class test {
    public static void main(string[] args) {

        abstractcake ac=new cake();
        ac=new fruitdecorator(ac);
        ac=new sugerdecorator(ac);
        system.out.println(ac.getcake());

    }
}

结果

具体的内存图

  可以很清楚的看见ac这个抽象类下面一层层包着实体类,解析的时候每一层的包装类的getcake()方法都会送回给抽象实体类,而我的getcake()方法实现的是字符串增加。后面如果我还需要一层水果,那么我就多装饰一次。如果用继承实现,那么我要两层水果,不要糖,那么我就还需要再定义一个实现两层水果的子类,而装饰者模式就只需要修改客户端的ac类实现就行。在jdk中装饰者模式用的最出名的莫过于io流了,以inputstream为例子。下面是uml图

 

  这就是典型的装饰者。平常我们只需要fileinputstream来读取文件,当我们有一些特殊功能需要,如:bufferedinputstream(完成了缓存功能,使读取文件速度大大提升)和datainputstream(把byte转换成java基本数据类型)我们就可以装饰一下inputstream,即灵活又方便。这样使得我们对fileinputstream流的处理更能达到我们想要的预期。当你理解了装饰者模式,我推荐你看这篇博客。这样你就能很好的理解io流的操作。

总结

  装饰者模式是一个比继承更加灵活的扩展方式,要记住装饰者模式必不可少的4个类:抽象的实体类,具体的实体类,抽象的装饰者,具体的装饰者。再结合上面推荐的博客,我相信你不但能理解装饰者,还能更加清晰的理解jdk中的io流

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网