设计模式学习07----之装饰者模式

概述

上一篇我们学习了适配器模式,今天我们接着学习装饰模式。

定义和结构

装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供比继承更有弹性的替代方案
装饰模式
装饰模式的角色有:
1. 抽象组件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
2. 具体组件(ConcreteComponent)角色:定义一个将要接收附加责任的类
3. 装饰者(Decorator)角色: 持有一个构件对象的实例。并实现一致的接口。
4. 具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加的责任。

以咖啡调料品为例

假设有这样一个场景:张三买了一杯25元的美式咖啡,喝了几口,太苦了。然后加了2元一份的糖包(sugar),李四买了一杯30元的拿铁,然后在里面加了一份5元的牛奶(milk)。这样一种情况,就属于装饰器模式,咖啡作为组件,调料包作为装饰器。

类图

调咖啡类图
抽象咖啡类(Coffee)

package com.decorate;

/**
 * 抽象咖啡类
 *
 * @author xiang.wei
 * @create 2018/4/10 19:44
 */
public abstract class Coffee {
    //咖啡信息
    private String coffeeInfo = "普通咖啡";

    public String getCoffeeInfo() {
        return coffeeInfo;
    }

    public abstract int cost();
}

具体咖啡类

package com.decorate;

/**
 * 美式咖啡类
 * @author xiang.wei
 * @create 2018/4/11 13:50
 */
public class Americano extends Coffee {
    @Override
    public String getCoffeeInfo() {
        return "美式咖啡";
    }

    @Override
    public int cost() {
        return 25;
    }
}
package com.decorate;

/**
 * 拿铁类
 *
 * @author xiang.wei
 * @create 2018/4/11 13:49
 */
public class Latte extends Coffee {
    @Override
    public String getCoffeeInfo() {
        return "拿铁";
    }

    @Override
    public int cost() {
        return 30;
    }
}

调料类(Flavour):

package com.decorate;

/**
 * 配料抽象类
 * @author xiang.wei
 * @create 2018/4/11 13:54
 */
public abstract class Flavour extends Coffee {
    @Override
    public abstract String getCoffeeInfo();

}

调料类(Flavour)继承了咖啡类(Coffee),并重写了getCoffeeInfo()方法。
具体调料类

package com.decorate;

/**
 * 配料牛奶类
 *
 * @author xiang.wei
 * @create 2018/4/11 13:54
 */
public class Milk extends Flavour {
    private Coffee coffee;

    public Milk(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public String getCoffeeInfo() {
        return coffee.getCoffeeInfo()+"加了牛奶";
    }

    @Override
    public int cost() {
        return coffee.cost()+5;
    }
}
package com.decorate;

/**
 * 配料糖类
 *
 * @author xiang.wei
 * @create 2018/4/11 13:54
 */
public class Sugar extends Flavour {
    private Coffee coffee;

    public Sugar(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public String getCoffeeInfo() {
        return coffee.getCoffeeInfo()+"加了糖";
    }

    @Override
    public int cost() {
        return coffee.cost()+3;
    }
}

客户端类:

package com.decorate;

/**
 * @author xiang.wei
 * @create 2018/4/11 14:18
 */
public class Client {
    public static void main(String[] args) {
        Coffee coffee1 = new Americano();
        Coffee coffee2 = new Latte();
        Flavour flavour = new Sugar(coffee1);
        System.out.println(flavour.getCoffeeInfo()+"现在的价格是:"+flavour.cost());
        Flavour flavour1 = new Milk(coffee2);
        System.out.println(flavour1.getCoffeeInfo()+"现在的价格是:"+flavour1.cost());

    }
}

运行结果是:

美式咖啡加了糖现在的价格是:28
拿铁加了牛奶现在的价格是:35

优缺点

  1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
  2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
  3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

参考

https://blog.csdn.net/a19881029/article/details/8980503
https://blog.csdn.net/yqynsmile/article/details/52673529

猜你喜欢

转载自blog.csdn.net/u014534808/article/details/79848159
今日推荐