1.简介
设想一下这样的场景:吃火锅时,锅底是必须点的,然后还可以往里面加豆腐,土豆和肉之类的食物,简言之,除了锅底这个必点的主体之外,还可以添加其它的配菜。这个时候就可以考虑用装饰者模式去设计这个场景需要的系统。
装饰者模式 动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰者模式中比较核心的有四个角色:
1.核心抽象类,装饰者和被装饰者(主体)都需要继承这个抽象类。
2.被装饰者,主体,必须继承核心抽象类。
3.装饰者,装饰者的抽象接口,抽象出具体需要装饰的接口。
4.具体的装饰者,继承装饰者,是具体的装饰者实现类
下面是一个关于装饰者模式的UML图
2.代码实现
沿用之前火锅的例子,直接上代码
先定义一个核心抽象类Food
public abstract class Food {
private String desc;
public String getDesc() {
return this.desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public abstract double cost();
}
再就是被装饰者(主体)
public class HotPot extends Food {
public HotPot() {
this.setDesc("火锅");
}
@Override
public double cost() {
//锅底单价20元
return 20D;
}
}
然后是装饰者抽象类
public abstract class FoodDecorator extends Food {
public abstract String getDesc();
}
具体的装饰者实现类,首先是豆腐
public class Tofu extends FoodDecorator {
private Food food;
private final String NAME = "豆腐";
public Tofu(Food food) {
this.food = food;
}
@Override
public String getDesc() {
return food.getDesc() + " + " + NAME;
}
@Override
public double cost() {
//每份豆腐4元
return food.cost() + 4D;
}
}
土豆
public class Potatoes extends FoodDecorator {
private Food food;
private final String NAME = "土豆";
public Potatoes(Food food) {
this.food = food;
}
@Override
public String getDesc() {
return this.food.getDesc() + " + "+ NAME;
}
@Override
public double cost() {
//每份土豆4元
return this.food.cost() + 4D;
}
}
肉
public class Meat extends FoodDecorator {
private Food food;
private final String NAME = "肉";
public Meat(Food food) {
this.food = food;
}
@Override
public String getDesc() {
return this.food.getDesc() + " + " + NAME;
}
@Override
public double cost() {
//肉10元一份
return this.food.cost() + 10D;
}
}
下面是测试类
public class Test {
public static void main(String[] args) {
Food hotPot = new HotPot();
Food tofu = new Tofu(hotPot);
Food potatoes = new Potatoes(tofu);
Food meat = new Meat(potatoes);
System.out.println(meat.getDesc());
System.out.println(meat.cost() + "元");
}
}
输出结果
火锅 + 豆腐 + 土豆 + 肉
38.0元
可以看到火锅最终被加上了一些配菜,并且也得到了总价
3. 总结
装饰者模式的优点:
- 装饰者和被装饰者相关的类被完全解耦,相互之间不需要知道其实现的过程。
- 装饰者模式很好地利用了继承这一面向对象的基本特征,无论被装饰多少层,其类型都是顶层的核心抽象类。
- 装饰者模式可以很好的用于动态地扩展类的功能
装饰者模式的缺点:
- 如果装饰的类的层数太多,一旦最里面或者比较核心的层次出现问题,查找问题的困难就会异常大。
装饰者模式实用案例:java.io
参考:
https://www.cnblogs.com/jamaler/p/11571592.html#4368820