装饰者模式
业务需求:
- 星巴克咖啡项目:单品咖啡,可以选择添加调料
- 咖啡种类:意大利、美式、无因、shortBlack
- 调料:牛奶、豆浆、巧克力
- 要求,扩展新的品类的咖啡,具有良好扩展性,改动方便,维护方便
- 用面向对象的思想计算不同咖啡的费用,客户可以单点咖啡,也可以咖啡+调料
方案一分析:
- Drink抽象类表示饮料,des是咖啡描述(名字),cost是计算费用(抽象方法)
- 咖啡+调料的组合很多,产生很多的类;每增加一个咖啡或调料,类的数量就会倍增,出现类爆炸
方案二分析:
- 方案二可以控制类的数量,不至于造成过多的类
- 增加或删除调料中类时,代码维护量仍然很大;
- 考虑到用户可以添加多份调料时,可以将has方法返回对应的int,比第一个方案略好,仍然不完美
- 可以考虑使用装饰者模式
装饰者模式定义
- 装饰者模式:动态的将新功能附加到对象上,,在对象功能扩展方面,他比继承更有弹性,装饰者模式也体现了开闭原则
需求设计方案
说明
- Drink类是抽象类
- ShortBlack是单品咖啡,Coffee是缓冲层
- Decorator是装饰类,需要含有一个被装饰的对象(Drink obj)
- Decorator的cost方法进行费用的叠加计算,递归计算价格
- milk包含了longblack
- 一份longblack包含了milk+longblack
- 一份chocolate包含了milk+longblack+chocolate
- 不论什么形式的单品咖啡+调料组合,通过递归的方式便可以组合和维护
代码实现
Drink父类
@Data
public abstract class Drink {
public String des;// 描述
private float price;// 价格
// 计费
public abstract float cost();
}
Coffee缓冲层
public class Coffee extends Drink {
@Override
public float cost() {
return super.getPrice();
}
}
具体咖啡类
public class Espresso extends Coffee {
public Espresso() {
setDes("意大利咖啡");
setPrice(6.0f);
}
}
public class LongBlack extends Coffee {
public LongBlack() {
setDes("LongBlack");
setPrice(5.0f);
}
}
public class ShortBlack extends Coffee {
public ShortBlack() {
setDes("ShortBlack");
setPrice(5.0f);
}
}
装饰者Decorator
public class Decorator extends Drink {
private Drink obj;
public Decorator(Drink obj) {
this.obj = obj;
}
@Override
public float cost() {
return super.getPrice()+ obj.cost();
}
@Override
public String getDes() {
return des+" & "+getPrice()+obj.getDes();
}
}
可以添加的调料
public class Chocolate extends Decorator {
public Chocolate(Drink obj) {
super(obj);
setDes("巧克力");
setPrice(3.0f);
}
}
public class Milk extends Decorator {
public Milk(Drink obj) {
super(obj);
setDes("牛奶");
setPrice(2.0f);
}
}
public class Soy extends Decorator {
public Soy(Drink obj) {
super(obj);
setDes("豆浆");
setPrice(1.5f);
}
}
客户端
public class CoffeeBar {
public static void main(String[] args) {
// 点一份longblack
Drink order = new LongBlack();
System.out.println("费用0= "+ order.cost());
System.out.println("描述0=" + order.getDes());
System.out.println("=================");
// 加入一份牛奶
order = new Milk(order);
System.out.println("order一份牛奶,费用1= "+ order.cost());
System.out.println("order一份牛奶,描述1= " + order.getDes());
System.out.println("=================");
// 加入一份巧克力
order = new Chocolate(order);
System.out.println("order一份巧克力,费用2= "+order.cost());
System.out.println("order一份巧克力,描述2= " + order.getDes());
System.out.println("=================");
// 再加入一份巧克力
order = new Chocolate(order);
System.out.println("order一份巧克力,费用3= "+order.cost());
System.out.println("order一份巧克力,描述3= " + order.getDes());
System.out.println("=================");
}
}
JDK源码分析—Java IO
Demo演示
public class DecoratorIO {
public static void main(String[] args) throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("d:\\abc.txt"));
System.out.println(dis.read());
dis.close();
}
}
- InputStream是抽象类,相当于Drink父类,其子类对应具体的饮品
- FileInputStream 是InputStream子类,相当于具体饮品
- FilterInputStream 就是装饰者抽象类,他的子类就相当于各种调味品
- DataInputStream是装饰者FilterInputStream 的子类,具体的装饰者,相当于装饰者
- 从基础的文件流,逐渐添加装饰,一层层套在外面,就是装饰者模式的设计过程
- JDK在IO体系中主要使用的就是装饰者模式
版权声明:本文为weixin_47257749原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。