java23种设计模式之十一:装饰者模式

一.应用场景

如果你在遇到需要动态的给一个对象增加新的属性(变量)和行为(方法),而这些属性和行为又在一个独立的类中,那么,你可以了解一下装饰者模式。

优点:可以更方便、更灵活的为一个对象动态的增加功能和属性,如果用生成子类的方法,会造成类膨胀

并且还会产生很多冗余代码。

缺点:需要你细细体会和深入了解

二.名词解释

1.Component(主体类:被装饰对象的基类)

定义一个抽象类或接口,定义一些属性和行为

2.ConcreteComponent(主体实现类:具体被装饰对象)

定义一个类,继承或实现主体类中的属性和行为。

3.Decorator(装饰类)

定义一个装饰者类,添加一个主体类的属性,并实现或定义一个与主体类接口一致的接口。

4.ConcreteDecorator(装饰实现类1)

定义一个类,继承装饰者类,可以在内部封装具体的属性和行为,增加具体的功能。

 

三.需求

我想喝一杯饮料:

1.一杯咖啡,可以加牛奶、加巧克力

2.一杯奶茶,可以加牛奶、加巧克力

四.UML类图

  

五.示例

1.主体类

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  饮品-被装饰类
 * @createDate   2021/9/27 10:28
 * @updateDate   2021/9/27 10:28
 * @version      1.0
 */

public abstract class AbstractDrink {

    /**
     * 饮品名称
     */
    public String name;

    /**
     * 饮品价格
     */
    public float price;

    /**
     * 饮品描述
     */
    public String description;

    /**
     * 花费多少钱
     * @return float
     */
    public abstract float cost();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public float getPrice() {
        return price;
    }

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

}

2.主体实现类

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  咖啡-单品
 * @createDate   2021/9/27 10:31
 * @updateDate   2021/9/27 10:31
 * @version      1.0
 */

public class Coffee extends AbstractDrink {

    @Override
    public float cost() {
        return super.getPrice();
    }

    @Override
    public String getDescription() {
        return description + " 消费:" + cost() + "元";

    }

}

3.装饰类

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  装饰者-饮品
 * @createDate   2021/9/27 10:35
 * @updateDate   2021/9/27 10:35
 * @version      1.0
 */

public class DecoratorDrink extends AbstractDrink {

    public final AbstractDrink drink;

    public DecoratorDrink(AbstractDrink drink) {
        this.drink = drink;
    }

    @Override
    public float cost() {
        return super.getPrice() + drink.cost();
    }

    @Override
    public String getDescription() {
        return description + " 消费:" + cost()+ "元";
    }

}

4.装饰类实现一

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  巧克力
 * @createDate   2021/9/28 10:25
 * @updateDate   2021/9/28 10:25
 * @version      1.0
 */

public class Chocolate extends DecoratorDrink{

    public Chocolate(AbstractDrink drink) {
        super(drink);
        setName("巧克力");
        setPrice(5.0f);
    }

}

5.装饰类实现二

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  牛奶咖啡
 * @createDate   2021/9/27 11:36
 * @updateDate   2021/9/27 11:36
 * @version      1.0
 */

public class MilkCoffee extends DecoratorDrink {

    public MilkCoffee(AbstractDrink drink) {
        super(drink);
    }

}

6.测试类

package com.zpb.decorate;

/**
 * @author       pengbo.zhao
 * @description  咖啡-测试类
 * @createDate   2021/9/27 11:40
 * @updateDate   2021/9/27 11:40
 * @version      1.0
 */

public class CoffeeTest {

    public static void main(String[] args) {

        // 咖啡单品
        Coffee coffee = new Coffee();
        coffee.setName("咖啡");
        coffee.setPrice(10.f);
        coffee.setDescription("单品咖啡");
        System.err.println(coffee.getDescription());

        // 咖啡 + 牛奶
        MilkCoffee milkCoffee = new MilkCoffee(coffee);
        milkCoffee.setName("牛奶");
        milkCoffee.setPrice(3.0f);
        milkCoffee.setDescription("单品咖啡 + 牛奶");
        System.err.println(milkCoffee.getDescription());

        // 咖啡 + 牛奶 + 巧克力
        Chocolate chocolate = new Chocolate(milkCoffee);
        chocolate.setName("巧克力");
        chocolate.setPrice(5.0f);
        chocolate.setDescription("单品咖啡 + 牛奶 + 巧克力");

        System.err.println(chocolate.getDescription());

        
    }

}

// 输出结果
// 单品咖啡 消费:10.0元
// 单品咖啡 + 牛奶 消费:13.0元
// 单品咖啡 + 牛奶 + 巧克力 消费:18.0元

 

六.总结

通过示例,我们通过咖啡这个单品,来不断增加咖啡这个类的属性,当然,我们也可以通过产生新的主体实现类,通过已有的装饰者实现类来增强属性。

 

 

 

 

 

posted @ 2021-09-28 17:18  硝烟漫过十八岁  阅读(648)  评论(0编辑  收藏  举报