概述
上一篇我们学习了适配器模式,今天我们接着学习装饰模式。
定义和结构
装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供比继承更有弹性的替代方案
装饰模式的角色有:
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
优缺点
这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
参考
https://blog.csdn.net/a19881029/article/details/8980503
https://blog.csdn.net/yqynsmile/article/details/52673529