设计模式之装饰者模式 简单实例+理解
仅代表我个人理解 下面是一个示例 我们点咖啡时可以选择调料 如下:
饮料: 咖啡
材料: 砂糖 牛奶
那我们是不是有 咖啡+砂糖 咖啡+牛奶 咖啡+砂糖+牛奶 咖啡 4种选择
以咖啡为父类 其他三种以子类形式继承父类 对应实现各自的需求 但是随着材料增多 组合增加 子类过多 会非常棘手 所以使用装饰者模式,顾名思义,我们准备一杯咖啡,然后用调料来装饰它,从代码的层面来讲,我们写一个需要装饰的装饰者类,然后只需要写对应装饰品类,需要哪个装饰品就将他放到装饰者类中。
装饰模式的基本uml图
看的出来 如果需要加材料 只需要再写一个类就行了 不用担心组合的问题 至于为什么 上代码(可以直接将代码复制 并粘贴到包下 会自动生成类)
抽象类Coffee
//之所以使用抽象类 因为可能不止一个抽象对象
public abstract class Coffee {
public abstract String create();
public abstract int price();
}
装饰者类
//装饰者类
public class CoffeeDecorator extends Coffee {
private Coffee coffee;
public CoffeeDecorator(Coffee coffee){
this.coffee=coffee;
}
@Override
public String create() {
return coffee.create();
}
@Override
public int price() {
return coffee.price();
}
}
星巴克咖啡
//星巴克
public class StarbucksCoffee extends Coffee {
@Override
public String create() {
return "一杯星巴克";
}
@Override
public int price() {
return 20;
}
}
瑞幸咖啡
public class LuckyCoffee extends Coffee {
@Override
public String create() {
return "一杯瑞幸咖啡";
}
@Override
public int price() {
return 10;
}
}
牛奶
public class Milk extends CoffeeDecorator {
public Milk(Coffee coffee) {
super(coffee);
}
@Override
public String create() {
return super.create()+"加一杯牛奶";
}
@Override
public int price() {
return super.price()+2;
}
}
糖
public class Sugar extends CoffeeDecorator {
public Sugar(Coffee coffee) {
super(coffee);
}
@Override
public String create() {
return super.create()+"加一勺糖";
}
@Override
public int price() {
return super.price()+1;
}
}
demo测试类
public class demo {
public static void main(String[] args) {
Coffee luckyCoffee = new LuckyCoffee();
luckyCoffee=new Ice(luckyCoffee);
luckyCoffee=new Milk(luckyCoffee);
luckyCoffee=new Sugar(luckyCoffee);
luckyCoffee=new Sugar(luckyCoffee);
luckyCoffee=new Milk(luckyCoffee);
Coffee starbucksCoffee = new StarbucksCoffee();
starbucksCoffee=new Milk(starbucksCoffee);
starbucksCoffee=new Sugar(starbucksCoffee);
starbucksCoffee=new Sugar(starbucksCoffee);
starbucksCoffee=new Milk(starbucksCoffee);
starbucksCoffee=new Ice(starbucksCoffee);
System.out.println(luckyCoffee.create());
System.out.println(luckyCoffee.price());
System.out.println(starbucksCoffee.create());
System.out.println(starbucksCoffee.price());
}
}
运行结果;
一杯瑞幸咖啡加冰加一杯牛奶加一勺糖加一勺糖加一杯牛奶
17
一杯星巴克加一杯牛奶加一勺糖加一勺糖加一杯牛奶加冰
27
程序结束 在这之中有一个疑问 为什么装饰类要使用静态代理呢?
换一个角度思考 如果不适用 那么我们的装饰品类应该是这样的
//在实现类里写装饰也可以 但是每个都要写 很麻烦 所以统一写到decorator中
public class Ice extends Coffee{
private Coffee coffee;
public Ice(Coffee coffee){
this.coffee=coffee;
}
@Override
public String create() {
return coffee.create()+"加冰";
}
@Override
public int price() {
return coffee.price()+1;
}
}
每一个装饰品类都要写静态代理 非常麻烦 所以统一写一个 效率更高(个人理解)
而且使用装饰者模式可以想加多少加多少 例如 我想加5份牛奶 那只要Milk创建5次即可
如果不使用装饰者模式 代码上就要做很大的改动
附加
1.装饰者模式是 is-a 的实现 (继承)
2.实现了开闭原则 对修改关闭 对拓展开放
3.抽象类的作用是可以让这个类有更多的实现 如果只有一种实现的情况 可以不写抽象类