概述
上一篇我们学习了适配器模式,今天我们接着学习装饰模式。
定义和结构
装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供比继承更有弹性的替代方案
装饰模式的角色有:
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