设计模式——装饰者模式

◇◆丶佛笑我妖孽 提交于 2019-11-26 14:53:51

装饰者模式

1. 定义

装饰者模式动态的将责任附加到对象上。如要扩展功能,装饰者提供了比继承更有弹性的替代方案。

2. 类图

3. Example

假如有这样一个需求:有一天,奶茶店的老板喊你给他们做一个简单版的计算价格程序。新店开张,供应的饮料有奶茶(8元)、红茶(7元)、绿茶(5元)三种,提供的配料有波霸1元,布丁5元,红豆3元。

则可如下设计:

Component及其实现如下:

package com.gitlearning.hanldegit.patterns.decorator;

/**
 * 相当于Component
 */
public abstract class Beverage {
    String description = "Unkown beverage";

    public String getDescription() {
        return description;
    }

    public abstract double cost();

}

class MilkTea extends Beverage {
    @Override
    public String getDescription() {
        return "奶茶";
    }

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

class RedTea extends Beverage {
    @Override
    public String getDescription() {
        return "红茶";
    }

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

class GreenTea extends Beverage {
    @Override
    public String getDescription() {
        return "绿茶";
    }

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

Decorator及其实现如下:

package com.gitlearning.hanldegit.patterns.decorator;

public abstract class CondimentDecorator extends Beverage {
    @Override
    public abstract String getDescription();


}

class RedBean extends CondimentDecorator {

    Beverage beverage;

    public RedBean(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + "添加红豆";
    }

    @Override
    public double cost() {
        return beverage.cost() + 3.00;
    }
}

class Pudding extends CondimentDecorator {
    Beverage beverage;

    public Pudding(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + "添加布丁";
    }

    @Override
    public double cost() {
        return beverage.cost() + 5.00;
    }
}

class Boba extends CondimentDecorator {
    Beverage beverage;

    public Boba(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + "添加波霸";
    }

    @Override
    public double cost() {
        return beverage.cost() + 1.00;
    }
}

测试代码如下:

package com.gitlearning.hanldegit.patterns.decorator;

import org.junit.jupiter.api.Test;

public class DecoratorTest {
    @Test
    void test() {
        // 来一杯加波霸和布丁的奶茶
        Beverage milkTea = new MilkTea();
        milkTea = new Pudding(milkTea);
        milkTea = new Boba(milkTea);
        System.err.println(milkTea.getDescription() + "¥"+ milkTea.cost());

        // 来一杯加红豆的绿茶
        Beverage greenTea = new GreenTea();
        greenTea = new RedBean(greenTea);
        System.err.println(greenTea.getDescription() + "¥"+ greenTea.cost());

        // 来一杯加红豆、布丁、波霸的红茶
        Beverage redTea = new RedTea();
        redTea = new Pudding(redTea);
        redTea = new Boba(redTea);
        redTea = new RedBean(redTea);
        System.err.println(redTea.getDescription() + "¥"+ redTea.cost());
    }
}

发现输出为:

奶茶添加布丁添加波霸¥14.0
绿茶添加红豆¥8.0
红茶添加布丁添加波霸添加红豆¥16.0

4. 使用

1. Java I/O

InputStream作为抽象Component,

Component,像BufferedInputStream装饰了FileInputStream,增加了readLine()和缓冲输入,LineNumberInputStream()则增加了计算行数的能力。

2. Mybatis

5.其他

  1. 装饰者会导致类中出现许多的小对象,如果过度使用,会让程序变得复杂。
  2. 装饰者可以在被装饰者的行为前面或者后面加上自己的行为。
  3. 可以用无数个装饰者包装一个组件。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!