前言(一些废话,可以忽略)
- 又是一个通过聚合方式来展现设计模式思想的一个典型案例,直接进入正题
- PS.部分类实现见文末
解决一个问题
- 咖啡店点咖啡,如果我们要一份美式,要加糖,加牛奶,很简单,但是不仅有美式,还有其他不同种的咖啡单品,那么就有多重组合方式,如果这时我们需要增加伴侣,如加珍珠,那么就会遇到和上一个结构型模式一样的问题,类爆炸
- 如果解决这个问题呢,当然是装饰者模式,将咖啡用户各种伴侣灵活的封装起来,这样就可以不用担心在扩展的时候类爆炸的问题了
装饰者模式
- 装饰者的核心,就是装饰者要继承和聚合同一个类,个人感觉这也就是和桥接模式最大的不同
- 我们的饮料类,有描述和每一种饮料的花费,也就是我们的伴侣要包含和继承的类
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-28 28:19
**/
public abstract class Drink {
private String desc;
public Drink(String desc) {
this.desc = desc;
}
String getDesc(){
return desc;
}
abstract float cost();
}
-接下来看我们的单品咖啡,价格2.0,名字就叫LongBlack
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-28 28:19
**/
public class LongBlack extends Drink {
public LongBlack() {
super("LongBlack");
}
@Override
float cost() {
return 2.0f;
}
}
- 而伴侣,如牛奶伴侣,继承我们的装饰者,那装饰者又有什么呢
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-28 28:20
**/
public class Milk extends Decorator {
public Milk(Drink drink) {
super(drink);
}
@Override
String getDesc() {
return "加牛奶1份+"+drink.getDesc();
}
@Override
float cost() {
return drink.cost()+0.5f;
}
}
- 装饰者当然就是我们之前说的,继承饮料同时聚合饮料,这样,我们在使用的时候就可以随意加我们想要的伴侣了
/**
* 调料
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-28 28:20
**/
public abstract class Decorator extends Drink{
Drink drink;
public Decorator(Drink drink) {
super(drink.getDesc());
this.drink = drink;
}
}
- 装饰者模式的使用如下,方便灵活好扩展
/**
* @program: ade-someproblem
* @author: cade franklin
* @create: 2019-12-28 28:20
**/
public class DecoratorMode {
public static void main(String[] args) {
Drink drink = new Milk(new Chocolate(new LongBlack()));
System.out.println(drink.getDesc());
System.out.println(drink.cost());;
}
}
总结
- 此模式与上一篇介绍的桥接模式比较相似,都是通过聚合的方式来实现,但是对象之间的关系不同,这个是多个装饰者,一个单品,一对多的关系,而上一篇桥接模式,是多对多的关系,多个手机品牌,多个屏幕类型,在学习时,可以进行适当的区分
- 另外此模式的核心逻辑在前面已经说了,就是装饰者要聚和一个被装饰者,他们当然也要继承同样的类
愿你不舍爱与自由。