以咖啡订单引入装饰者模式
客户可以点单品咖啡,也可以单品咖啡+调料组合。
方案一
比较差的设计样例,耦合度过高。
如果说要添加扩展新的单品咖啡或者组合口味的咖啡,类的数量增加,就会引发"类爆炸"。

方案二
将调料内置到Drink类,不会造成类数量过多。
但是,添加或者删除调味品的种类时,需要改动维护。

动态的将新功能附加到对象上
在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)。
装饰者模式就像打包一个快递
Component 主体:比如类似前面的 Drink
ConcreteComponent:具体的主体, 比如前面的各个单品咖啡
Decorato:装饰者,比如各调料
如果 ConcreteComponent 类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象成一个类。
思路分析

抽象类饮品
- public abstract class Drink {
- //对饮品的描述
- private String description;
- //价格
- private float price;
-
- //计算价格,由子类实现
- public abstract float cost();
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setPrice(float price) {
- this.price = price;
- }
-
- public float getPrice() {
- return price;
- }
- }
缓冲类Coffee
- public class Coffee extends Drink{
- @Override
- public float cost() {
- return super.getPrice();
- }
- }
两种Coffee
- public class LongBlackCoffee extends Coffee{
- public LongBlackCoffee(){
- setDescription("一份美式咖啡");
- setPrice(7.0f);
- }
- }
- public class ShortBlackCoffee extends Coffee {
- public ShortBlackCoffee(){
- setDescription("一份浓缩咖啡");
- setPrice(5.0f);
- }
- }
装饰者Decorator
- //装饰者
- public class Decorator extends Drink{
- //被装饰者;
- private Drink drink;
-
- public Decorator(Drink drink){
- this.drink = drink;
- }
-
- @Override
- public float cost() {
- return super.getPrice() + drink.cost();
- }
-
- @Override
- public String getDescription(){
- return drink.getDescription() + " && " +
- super.getDescription() + super.getPrice();
- }
- }
两种调味品
- public class Milk extends Decorator{
- public Milk(Drink drink) {
- super(drink);
- setDescription("一份牛奶");
- setPrice(2.0f);
- }
- }
- public class Chocolate extends Decorator{
- public Chocolate(Drink drink) {
- super(drink);
- setDescription("一份巧克力");
- setPrice(1.0f);
- }
- }
模拟客户下单
- public class Client {
- public static void main(String[] args) {
- //两份巧克力+一份牛奶的美式咖啡;
- //1.先点美式咖啡;
- Drink result = new LongBlackCoffee();
- System.out.println("步骤一::" + result.getDescription());
- System.out.println("本次花费==>" + result.cost());
-
- //2.加份牛奶;
- result = new Milk(result);
- System.out.println("步骤二::" + result.getDescription());
- System.out.println("本次花费==>" + result.cost());
-
- //3.加份巧克力;
- result = new Chocolate(result);
- System.out.println("步骤三::" + result.getDescription());
- System.out.println("本次花费==>" + result.cost());
-
- //4.加份巧克力;
- result = new Chocolate(result);
- System.out.println("步骤四::" + result.getDescription());
- System.out.println("最终花费==>" + result.cost());
- }
- }
输出
步骤一::一份美式咖啡
本次花费==>7.0
步骤二::一份美式咖啡 && 一份牛奶2.0
本次花费==>9.0
步骤三::一份美式咖啡 && 一份牛奶2.0 && 一份巧克力1.0
本次花费==>10.0
步骤四::一份美式咖啡 && 一份牛奶2.0 && 一份巧克力1.0 && 一份巧克力1.0
最终花费==>11.0
Java 的 IO 结构,FilterInputStream 就是一个装饰者

- public class Test {
- public static void main(String[] args) throws IOException {
- DataInputStream dataInputStream = new DataInputStream(new FileInputStream("e:\\a.txt"));
- System.out.println(dataInputStream.read());
- dataInputStream.close();
- }
- }
说明
- public class FilterInputStream extends InputStream {
- protected volatile InputStream in;
-
- protected FilterInputStream(InputStream var1) {
- this.in = var1;
- }
分析得出在 JDK 的 IO 体系中,就是使用装饰者模式