装饰者模式

基本介绍:
装饰者模式:动态的将新功能附加到对象上,在对象功能扩展方面,它比继承更具有弹性,装饰者模式也体现了开闭原则(ocp),装饰者模式也可以理解为包装模式。

例如: 我们要寄一个手机,发快递我们的操作应该如下

  1. 把手机用防震膜包裹起来,这是第一层的装饰
    在这里插入图片描述
  2. 接下来我们得用快递盒进行包装
    在这里插入图片描述
  3. 最后再用塑料袋子封装好
    在这里插入图片描述

    这样一个手机就完成了包装,装饰者模式就是这样的原理,下面来看具体的说明:

  • 类图表示
    在这里插入图片描述

(1)Component

定义一个抽象类,用于接收动态添加的需求。

(2)ConcreteComponent

ConcreteComponent是我们要动态加上新行为的对象。

(3)Decorator

每一个装饰者都持有一个构件(Component)对象的实例,

也就是说,装饰者有一个实例变量以保存某个Component的引用,

(4)ConcreteDecorator

真正的装饰者,负责给对象添加新的方法和行为。

第一个例子:

被装饰者抽象类:Beverage
被装饰者:Espresso,HouseBlend
装饰者抽象类:CondimentDecorator
装饰者:Mocha

  • 具体实现代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    /**
    * 被装饰者的抽象类:饮料
    */
    public abstract class Beverage {

    String description = "Unknown Beverage";

    //成本
    public abstract double cost();

    //得到描述信息
    public String getDescription(){
    return description;
    }
    }

    /**
    * 被装饰者:浓咖啡
    */
    public class Espresso extends Beverage {

    public Espresso() {
    description = "Espresso";
    }

    @Override
    public double cost() {
    return 2;
    }
    }

    /**
    * 被装饰者:混合咖啡
    */
    public class HouseBlend extends Beverage {
    public HouseBlend() {
    description = "House Blend";
    }

    @Override
    public double cost() {
    return 1;
    }
    }

    /**
    * 装饰者的抽象类:调料
    */
    public abstract class CondimentDecorator extends Beverage {

    public abstract String getDescription();

    @Override
    public double cost() {
    return 0;
    }
    }

    /**
    * 装饰者:摩卡
    */
    public class Mocha extends CondimentDecorator {

    //聚合被装饰者,可以传入实现Beverage接口的所有对象
    Beverage beverage;
    //构造器,初始化beverage
    public Mocha(Beverage beverage) {
    this.beverage = beverage;
    }

    @Override
    public String getDescription() {
    return beverage.getDescription()+",Mocha";
    }

    @Override
    public double cost() {
    //调用被装饰者的成本,加上装饰者的成本
    return 3 + beverage.cost();
    }
    }

    /**
    * 测试
    */
    public class CoffeeTest {
    public static void main(String[] args) {

    Beverage beverage = new Espresso();
    //一杯浓咖啡为2元
    System.out.println(beverage.getDescription()+","+beverage.cost());

    Beverage beverage1 = new HouseBlend();
    //一杯混合咖啡(1)加摩卡(3)为4元
    // 在单个混合咖啡中包装了摩卡
    beverage1 = new Mocha(beverage1);
    System.out.println(beverage1.getDescription()+","+beverage1.cost());

    //一杯混合咖啡(1)加摩卡(3)加摩卡(3)为7元
    //可以在包装好的基础上再次进行包装
    beverage1 = new Mocha(beverage1);
    System.out.println(beverage1.getDescription()+","+beverage1.cost());
    }
    }
  • 运行结果
    在这里插入图片描述

    我们发现,写的包装起作用了,可以实现包装功用了!

  • 类图形式
    在这里插入图片描述

    第二个例子:

  • 结构图
    在这里插入图片描述
  • 代码实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    /**
    * 被装饰者抽象类
    */
    public abstract class Drink {

    public String des;//描述
    private float price = 0.0f;

    public String getDes() {
    return des;
    }

    public void setDes(String des) {
    this.des = des;
    }

    public float getPrice() {
    return price;
    }

    public void setPrice(float price) {
    this.price = price;
    }

    //计算费用的抽象 方法
    public abstract float cost();
    }

    /**
    * 缓冲层
    */
    public class Coffee extends Drink {
    @Override
    public float cost() {
    return super.getPrice();
    }
    }

    /**
    * 被装饰者:意大利咖啡
    */
    public class Espresso extends Coffee {

    public Espresso(){
    setDes("意大利咖啡");
    setPrice(6.0f);
    }
    }


    /**
    * 装饰者抽象类:
    */
    public class Decorator extends Drink {
    private Drink obj;

    public Decorator(Drink obj) {//组合
    this.obj = obj;
    }

    @Override
    public float cost() {
    //getPrice自己的价格
    return super.getPrice() + obj.cost();
    }


    public String getDes(){
    //obj.getDes()被装饰者的信息
    return super.des+" "+super.getPrice()+"&&"+obj.getDes();
    }
    }


    /**
    * 被装饰者:LongBlack
    */
    public class LongBlack extends Coffee {
    public LongBlack() {
    setDes("LongBlack");
    setPrice(5.0f);
    }
    }

    /**
    * 被装饰者:ShortBlack
    */
    public class ShortBlack extends Coffee {
    public ShortBlack() {
    setDes("ShortBlack");
    setPrice(4.0f);
    }
    }

    /**
    * 装饰者:
    */
    public class Milk extends Decorator {
    public Milk(Drink obj) {
    super(obj);
    setDes("牛奶");
    setPrice(2.0f);
    }

    }

    /**
    * 装饰者:
    */
    public class Soy extends Decorator {
    public Soy(Drink obj) {
    super(obj);
    setDes("豆浆");
    setPrice(1.5f);
    }
    }

    /**
    * 装饰者:
    */
    public class Chocolate extends Decorator {

    public Chocolate(Drink obj) {
    super(obj);
    setDes("巧克力");
    setPrice(3.0f);
    }
    }

    public class CoffBar {
    public static void main(String[] args) {

    //1.点一份LongBlank
    Drink order = new LongBlack();
    System.out.println("费用1="+order.cost());
    System.out.println("描述="+order.getDes());

    //2.加一份牛奶
    order = new Milk(order);
    System.out.println("加入一份牛奶后的费用1="+order.cost());
    System.out.println("描述="+order.getDes());

    //3.加入一份巧克力
    order = new Chocolate(order);
    System.out.println("加入一份牛奶,一份巧克力后的费用1="+order.cost());
    System.out.println("描述="+order.getDes());
    }
    }
  • 运行结果
    在这里插入图片描述
  • 类图形式
    在这里插入图片描述

    java I/O

    在这里插入图片描述
  • 从JDK源码中我们可以发现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    //装饰者抽象类类继承了被装饰者:InputStream 
    public class FilterInputStream extends InputStream {
    /**
    * The input stream to be filtered.
    */
    //聚合了抽象组件componment
    protected volatile InputStream in;

    /**
    * Creates a <code>FilterInputStream</code>
    * by assigning the argument <code>in</code>
    * to the field <code>this.in</code> so as
    * to remember it for later use.
    *
    * @param in the underlying input stream, or <code>null</code> if
    * this instance is to be created without an underlying stream.
    */
    //利用构造方法初始化InputStream
    protected FilterInputStream(InputStream in) {
    this.in = in;
    }
    ----------------------------------------------------------------------------------------
    //被装饰者继承抽象类InputStream
    public
    class FileInputStream extends InputStream
    {
    .......
    }
    ----------------------------------------------------------------------------------------
    //实际的装饰者继承装饰者抽象类
    public
    class DataInputStream extends FilterInputStream implements DataInput {

    ...
    }

    小结:

1.装饰者模式意味着一群装饰者类,这些类用来包装具体组件。
2.装饰者类反映 出被装饰的组件类型(事实上,他们具有相同的类型,都经过接口或继承实现)。
3.装饰者可以在被装饰者的行为前面/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
4.你可以用无数个装饰者包装一个组件。
5.装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型。