业务需求
咖啡馆多种咖啡,多种配料。需要单件咖啡加多种不同的配料,也可以单点咖啡。需要完成这个需求的设计,需要扩展性好可读性强。你会怎么设计呢?
解决方案
下面给出两种方案,凸显出装饰者模式的优缺点。
常规方案
给咖啡与配料各一个抽象类,咖啡与配料需继承各自抽象类,抽象类中有商品描述与价格。通过创建对象获取价格与描述,获取到该订单的价格与商品详情信息。从而实现了该需求。代码我就不贴出来了,大家可以想象,在很多很多配料与咖啡种类的情况下,计算一笔详情很麻烦,而且在扩展性上面显得很臃肿不堪。下面来看一下装饰者模式给出的解决方案。
装饰者模式
动态的将新功能附加到对象上,在对象功能扩展方面它比继承更有弹性,也体现出了开闭原则。先不着急看懂,我先简单的解释一下,心中有一个概念,在一对多的情况下先分清装饰者(多)与被装饰者(少),再给他们一个主体来简易开发,给咖啡与配料各自的缓冲类,详细的产品去实现详细的类即可。下面我们来看一下代码。
主体
public abstract class Drink {
private String des; // 描述
private float price = 0.0f; // 价格
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
// 计算费用的抽象方法
public abstract float cost();
}
缓冲层
// 被装饰者
public class Coffee extends Drink {
@Override
public float cost() {
return super.getPrice();
}
}
// 装饰者
public class Decorator extends Drink {
// 通过构造器注入的方式引入被主体(装饰者)以方便获取咖啡信息
private Drink obj;
public Decorator(Drink obj) {
this.obj = obj;
}
@Override
public float cost() {
// getPrice 是配料的价格
return super.getPrice() + obj.cost();
}
@Override
public String getDes() {
// getDes 被装饰者信息
return super.getDes() + " " + super.getPrice() + "&&" +obj.getDes();
}
}
以下是产品的详细实现信息,只贴出部分详细可下载源码观看
public class Coffee1 extends Coffee {
public Coffee1() {
setDes("咖啡111");
setPrice(1.0f);
}
}
public class Dosing1 extends Decorator {
public Dosing1(Drink obj) {
super(obj);
setDes("配料111");
setPrice(1.0f);
}
}
可以看出来装饰者引入了被装饰者,通过构造器注入获取到了装饰者信息,然后通过调用相应的get方法获取相关信息。下面我们测试一下:
public class CoffeeTest {
public static void main(String[] args) {
// 装饰者模式下单 一份咖啡 多种配料
Drink drink = new Coffee1();
System.out.println("收钱" + drink.cost());
System.out.println("描述" + drink.getDes());
// 加配料
drink = new Dosing1(drink);
System.out.println("加入配料收钱" + drink.cost());
System.out.println("加入配料描述" + drink.getDes());
}
}
收钱1.0
描述咖啡111
加入配料收钱2.0
加入配料描述配料111 1.0&&咖啡111
Process finished with exit code 0
小结
装饰者模式要分清主体,装饰者与被装饰者。装饰者通过引入被装饰者获取信息,从而操作获取到自己的需求信息即可。优点如下:动态的将新功能附加到对象上,在对象功能扩展方面它比继承更有弹性,常规的实现很容易造成类的数量众多,难以维护。
详细远源码地址: github.com/Liyinzuo/De…
以上便是我对装饰者模式的简介,如果那里错误或者不足的地方欢迎指正。