美文网首页程序员
【Java设计模式】结构型模式-装饰模式

【Java设计模式】结构型模式-装饰模式

作者: 灰色孤星 | 来源:发表于2018-10-25 10:36 被阅读0次

源代码:https://gitee.com/AgentXiao/DecroatorPattern
要点:
1、装饰模式解决的问题
2、装饰模式的各个模块实现
3、装饰模式的优缺点
4、装饰模式和桥接模式的区别

一、场景引入

场景引入

如上图所示,有一个狗(Dog)类,下面有三个子类,分别是会飞的狗(FlyDog)、会游泳的狗(SwimDog)、会跑的狗(RunDog)。假设此时三个子类都是单一功能的,也就说FlyDog只会飞,游泳和跑步都不会。

如果此时需要一个既会飞也会跑的狗,我们可以通过继承的方式实现,一次类推,可以得到:

继承具有新功能的狗

这显然不是最好的方法!当功能非常多时,需要继承父类的子类数量将会大大增加!而装饰模式就是解决这个问题的一种设计模式。

二、装饰模式

装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能够扩展对象的新功能。使用对象的组合关系(区分于“组合设计模式”)代替继承关系,避免类型体系的快速膨胀。

简单地说,装饰模式用于动态增加一个对象的新功能,或成为功能增强。

装饰模式实现细节:

装饰模式实现细节.png

(1)抽象构建角色Component。这是真实对象和装饰对象都需要实现的接口,便于客户端可以使用相同的方式交互装饰对象和真实对象,指上文的Dog。
(2)真实对象ConcreteComponent。具体需要装饰的对象,定义为MyDog。
(3)装饰对象Decorator。持有一个抽象构件的引用(核心)。装饰对象接受所有客户端的请求,并把这些请求通过引用转发给真实对象。这样,就能在真实对象调用前后增加新的功能,定义为SuperDog。
(4)具体装饰对象ConcreteDecorator:指上文的Fly、Swim、Run。

三、装饰模式的实现

1、抽象角色

/**
 * @InterfaceName Dog
 * @Description 抽象构建角色
 * @Author xwd
 * @Date 2018/10/25 9:52
 */
public interface Dog {
    /**
     * @MethodName showPower
     * @Descrition 展示能力
     * @Param []
     * @return void
     */
    void showPower();
}

2、具体角色

/**
 * @ClassName MyDog
 * @Description 具体对象
 * @Author xwd
 * @Date 2018/10/25 9:53
 */
public class MyDog implements Dog{
    @Override
    public void showPower() {
        System.out.println("我还没有什么能力!");
    }
}

3、装饰角色(核心)

/**
 * @ClassName SuperDog
 * @Description 装饰对象
 * @Author xwd
 * @Date 2018/10/25 9:54
 */
public class SuperDog implements Dog{
    protected Dog dog;//持有抽象构建角色的引用

    public SuperDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public void showPower() {
        dog.showPower();
    }
}

4、具体的装饰角色

/**
 * @ClassName Fly
 * @Description 飞行能力
 * @Author xwd
 * @Date 2018/10/25 9:57
 */
public class Fly extends SuperDog{
    public Fly(Dog dog) {
        super(dog);
    }

    @Override
    public void showPower() {
        super.showPower();
        System.out.println("我具备飞行功能!");
    }
}
/**
 * @ClassName Run
 * @Description 奔跑能力
 * @Author xwd
 * @Date 2018/10/25 9:57
 */
public class Run extends SuperDog{
    public Run(Dog dog) {
        super(dog);
    }

    @Override
    public void showPower() {
        super.showPower();
        System.out.println("我具备奔跑功能!");
    }
}
/**
 * @ClassName Swim
 * @Description 游泳能力
 * @Author xwd
 * @Date 2018/10/25 9:57
 */
public class Swim extends SuperDog{
    public Swim(Dog dog) {
        super(dog);
    }

    @Override
    public void showPower() {
        super.showPower();
        System.out.println("我具备游泳功能!");
    }
}

5、测试

/**
 * @ClassName Client
 * @Description 测试装饰模式
 * @Author xwd
 * @Date 2018/10/25 9:59
 */
public class Client {
    public static void main(String[] args) {

        //原生态的狗,还没有什么能力
        Dog dog = new MyDog();
        dog.showPower();
        System.out.println("*********************");

        //添加了装饰模式的狗,但是还没有添加具体功能
        SuperDog superDog = new SuperDog(dog);
        superDog.showPower();
        System.out.println("*********************");

        //添加了飞行能力的狗
        SuperDog flyDog = new Fly(dog);
        flyDog.showPower();
        System.out.println("*********************");

        //添加了游泳能力的狗
        SuperDog swimDog = new Swim(dog);
        swimDog.showPower();
        System.out.println("*********************");

        //既添加了飞行能力又添加了奔跑能力的狗
        SuperDog runDog = new Run(dog);
        SuperDog fsDog = new Fly(runDog);
        fsDog.showPower();
        System.out.println("*********************");
    }
}

6、测试结果

测试结果

由此可见,需要为一个对象添加新功能时,只需要建立这个功能,将具体对象传入。如果传入的对象是已经具备某些功能的,就相当远在那个基础上添加新的功能。

四、开发中使用的场景

  • IO中输入流和输出流的设计。
  • Swing包中图形界面构件功能。
  • Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper类,增强了request对象的功能。
  • Struts2中,request,response,session对象的处理。

在这里只解释其中一种:
在IO流中,抽象构建对象是InputStream、OutputStream、Reader、Writer。

真实对象是FileInputStream、FileOutputStream。

真实对象

装饰对象是FilterInputStream、FilterOutputStream。

装饰对象

具体的装饰对象:BufferedOutputStream、BufferedInputStream等。

继承装饰对象 构造器中传入抽象构建对象

五、总结

1、功能

装饰模式(Decorator)也叫包装器模式(Wrapper)。

装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。

2、优点

  • 扩展对象功能,比继承灵活,不会导致类个数急剧增加。
  • 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象。
  • 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。

3、缺点

  • 产生很多小对象。大量小对象占据内存,一定程度上影响性能。
  • 装饰模式易于出错,调试排查比较麻烦。

4、装饰模式和桥接模式的区别

两个模式都是为了解决过多子类对象问题。但他们的诱因不一样。

  • 桥接模式是对象自身现有机制沿着多个维度变化。
  • 装饰模式是为了增加新的功能。

相关文章

  • JavaScript设计模式

    设计模式分类(23种设计模式) 创建型单例模式原型模式工厂模式抽象工厂模式建造者模式 结构型适配器模式装饰器模式代...

  • 常用的设计模式

    设计模式主要大概分成三类: 1.创建型:单例设计模式、抽象工厂设计模式 2.结构型:MVC 模式、装饰器模式、适配...

  • iOS常用设计模式总结(一)

    设计模式大概分成三类: 1.创建型:单例设计模式、抽象工厂设计模式 2.结构型:MVC 模式、装饰器模式、适配器模...

  • 设计模式(1)工厂模式

    设计模式有 23 种,按大类分的化可以分为三类 创建型(如:工厂模式、单例模式、原型模式等) 结构模式型(如:装饰...

  • 【设计模式】结构型设计模式汇总

    结构型设计模式汇总 结构型设计模式名称 结构型设计模式主要包括 7 大类: 代理模式 桥接模式 装饰器模式 适配器...

  • 开发之设计模式-单例模式

    设计模式 设计模式分为三大类:创建型、结构型、行为型在Java中有24中设计模式 创建型:单例 1、为什么用单例模...

  • 装饰者模式——IO流运用

    推荐博客Java设计模式学习09Java设计模式学习09Java设计模式学习09 装饰者模式还是比较难懂的。。。。...

  • JavaScript 设计模式核⼼原理与应⽤实践 之 结构型设计

    JavaScript 设计模式核⼼原理与应⽤实践 之 结构型设计模式 装饰器模式,又名装饰者模式。它的定义是“在不...

  • 设计模式之装饰器模式

    也称装饰者模式、装饰器模式、Wrapper、Decorator。 装饰模式是一种结构型设计模式,允许你通过将对象放...

  • Java日记之设计模式总结(结构型)

    前言 推荐看这篇文章之前先了解Java日记之设计模式初探。 结构型设计模式总共有7种 1.外观模式2.装饰者模式3...

网友评论

    本文标题:【Java设计模式】结构型模式-装饰模式

    本文链接:https://www.haomeiwen.com/subject/ppfqtqtx.html