设计模式——Decorator (装饰器) 模式

文章目录

        • 前言
        • 装饰器模式
          • 书面用语
          • 大白话
          • 装饰器模式需要四个基本组成部分
        • 构造一个场景
          • 场景描述
          • 场景探究
        • 装饰器模式给出的解决方案
          • 查看UML图
          • 代码
            • 抽象组件 VisualComponent.java
            • 具体构建 Car
            • 抽象装饰器 Decorator
            • 具体装饰器类 EngineDecorator
            • 具体装饰器类 TyreDecorator
            • 具体装饰器类 RadarDecorator
            • 测试类
        • 装饰器模式 适用场景
        • 装饰器模式的举例——Java IO
        • 装饰器模式的举例——Java 并发包 Collections
        • 参考链接

前言

体能状态先于精神状态,习惯先于决心,聚焦先于喜好。

装饰器模式

Decorator

书面用语

装饰器模式的意图是在运行时组合操作的新变化。
动态的给一个对象添加一些额外的职业。就增加功能来说,装饰器模式相比生成子类更为灵活。

大白话

装饰器模式的本质来说-增强一个对象的功能,
我们有很多种方式来达成一样的功能效果.比如子类继承父类、再比如使用代理模式
但是装饰器模式有其自身的特点,尤其是在代码实现上的特点:
1、装饰器模式不通过继承的方式进行增强——而是将对象作为一个变量,通过构造参数传递到装饰器类内部进行进一步处理,
这样你总是只有一个对象,但是你需要多少种特性就提供多少个装饰器类即可
2、对象所属类和装饰器类有共同的一个父抽象类(或者接口),在对象增强之后,对原对象的原方法的调用将转化为对修饰器类同名方法的调用,
在视觉感官上,保持了既有逻辑的一致性
通过1、2两点,你应该认识到修饰器模式不同于静态代理,它更像是对被修饰对象进行了一层封装,更为重要的是,这种代码结构提供了
一个非常重要的特性,即重复修饰,试想一下这种场景:一般人买汽车就是一辆汽车,但是顾客也可能需要其他服务,比如购买几个备用轮胎,
洗车、购买儿童座椅等等.每一个新的产品可以作为一个装饰器类,而可以通过重复调用来进行个数的增加-即重复修饰.

装饰器模式需要四个基本组成部分

抽象构件(Component):一个抽象类,包含一个抽象方法,被装饰类和装饰器类都需要继承这个抽象类
·具体构件(ConcreteComponent):即被装饰类,需要重写抽象方法
·抽象装饰(Decorator):一个继承了抽象构建的抽象类,作为具体装饰类的共同父类,该类不是必须的;含有一个全局抽象构件的变量-未实例化,并在提供一个以被修饰类对象为入参的构造方法,在构造方法内部将该对象赋值给全局声明的抽象构建变量
·具体装饰(ConcreteDecorator):一个继承了抽象装饰类的子类,重写抽象方法,一般在方法内部调用父类的同名方法,然后增加新的装饰逻辑

构造一个场景

场景描述

·用户购买轿车
·允许用户对轿车进行升级
·比如升级发动机,汽车轮胎,倒车雷达等

场景探究

·新轿车没啥
·升级即对新轿车这个对象进行修饰,升级发动机、汽车轮胎、倒车雷达等
·轮胎升级不止一个

装饰器模式给出的解决方案

查看UML图

设计模式——Decorator (装饰器) 模式_第1张图片

代码

注意本文所有代码没有包含 package,如测试请注意添加

抽象组件 VisualComponent.java
/**
 * 抽象组件
 */
public abstract class VisualComponent {
    /**升级*/
    public abstract String upgrade();
}

具体构建 Car
/**
 * 具体构件,即被修饰对象所属类
 */
public class Car extends VisualComponent {
    @Override
    public String upgrade() {
        return "购买原型车";
    }
}
抽象装饰器 Decorator
/**
 * 抽象装饰器类
 * 所有具体装饰器类继承自该类
 */
public abstract class Decorator extends VisualComponent{
    /**待修饰的对象*/
    private VisualComponent visualComponent;

    public Decorator(){}
    /**提供一个以被修饰对象为参数的构造函数
     * 子类构造函数可以直接调用父类的构造函数
     * */
    public Decorator(VisualComponent visualComponent){
        this.visualComponent=visualComponent;
    }

    @Override
    public String upgrade() {
        //该方法可以由子类来做具体实现
        return this.visualComponent.upgrade();
    }
}
具体装饰器类 EngineDecorator
/**
 * 升级 发动机 的具体装饰器类
 */
public class EngineDecorator extends Decorator {

    public EngineDecorator(){

    }

    /**子类提供传入被修饰对象的构造方法
     * 内部直接调用父类构造方法
     * */
    public EngineDecorator(VisualComponent visualComponent){
        super(visualComponent);
    }
    @Override
    public String upgrade() {

        return super.upgrade()+";升级发动机";
    }
}
具体装饰器类 TyreDecorator
/**
 * 升级 轮胎 的具体装饰器类
 */
public class TyreDecorator extends Decorator {
    public TyreDecorator(){

    }

    /**子类提供传入被修饰对象的构造方法
     * 内部直接调用父类构造方法
     * */
    public TyreDecorator(VisualComponent visualComponent){
        super(visualComponent);
    }
    @Override
    public String upgrade() {

        return super.upgrade()+";升级轮胎";
    }
}

具体装饰器类 RadarDecorator
/**
 * 升级 倒车雷达 的具体装饰器类
 */
public class RadarDecorator extends Decorator {
    public RadarDecorator(){

    }

    /**子类提供传入被修饰对象的构造方法
     * 内部直接调用父类构造方法
     * */
    public RadarDecorator(VisualComponent visualComponent){
        super(visualComponent);
    }
    @Override
    public String upgrade() {

        return super.upgrade()+";升级倒车雷达";
    }
}


测试类
import org.junit.Test;

public class DecoratorTest {
    @Test
    public void testUpgrade(){
        //购买车辆
        VisualComponent visualComponent=new Car();
        //升级发动机
        visualComponent=new EngineDecorator(visualComponent);
        //升级轮胎
        visualComponent=new TyreDecorator(visualComponent);
        //升级倒车雷达
        visualComponent=new RadarDecorator(visualComponent);

        String result=visualComponent.upgrade();
        System.out.println("result="+result);
    }
}

输出

result=购买原型车;升级发动机;升级轮胎;升级倒车雷达

装饰器模式 适用场景

如果一个对象包含很多种组合,以至于为组合的每一种情况提供一个单独的类不现实
这种情况下就适合用装饰器模式,通过每一个装饰器类对原对象进行功能扩展

装饰器模式的举例——Java IO

Java IO 体系非常完美的体现了 装饰器模式,分别用四个类来对应上文的距离
·抽象构建: InputStream
·抽象装饰者:FilterInputStream
·具体装饰者:BufferedInputStream
·具体构建:FileInputStream

装饰器模式的举例——Java 并发包 Collections

Collections 并发包提供方法,将非线程安全的对象封装到新对像内部,然后每一次操作增加一个 mutex 互斥锁.
是装饰器模式的实现.

ArrayList list=(ArrayList) Collections.synchronizedList(new ArrayList());

参考链接

[1]、https://blog.csdn.net/wwwdc1012/article/details/82764333
[2]、https://www.cnblogs.com/zuoxiaolong/p/pattern11.html
[3]、https://www.imooc.com/article/41726#
[4]、https://cloud.tencent.com/developer/article/1339008

你可能感兴趣的:(设计模式,设计模式)