装饰者(包装模式)
案例模拟
应用场景:老王是卖豆浆的,现在的豆浆品种不断增多,如下图,可以任意搭配,这种情况如果用继承的方式会形成 类爆炸,并且后期扩展也比较麻烦,这时候就可以用到装置者模式。适用于组合情况。
最终可以搭配的豆浆品种:
类图:
代码实现:
1.豆浆属于饮品,创建一个饮品的接口,后期可能还会卖果汁之类的其他饮品
/**
* 饮品
*/
public interface Drink {
//抽象组件
//价格
public double money();
//描述
public String desc();
}
- 创建被装饰者,豆浆,实现饮品Drink接口
/**
* 豆浆
* 豆浆属于饮品,所以要实现 Drink 这个接口
*/
public class Soya implements Drink{
//被装饰者
@Override
public double money() {
return 5;
}
@Override
public String desc() {
return "纯豆浆";
}
}
- 创建一个装饰器,它是一个抽象类,实现Drink,返回装饰后的结果
/**
* 抽象类
*/
public abstract class Decorator implements Drink{
//装饰器
//1.抽象类
//2.实现抽象组件接口
//3.持有抽象接口的引用
//定义私有的饮品接口引用
private Drink drink;
public Decorator(Drink drink){
this.drink = drink;
}
/**
* 重写方法,返回装饰后的结果
* @return
*/
@Override
public double money() {
return drink.money();
}
@Override
public String desc() {
return drink.desc();
}
}
4.具体装饰
鸡蛋
public class Egg extends Decorator {
public Egg(Drink drink) {
super(drink);
}
@Override
public double money() {
return super.money()+3.9;
}
@Override
public String desc() {
return super.desc()+"+鸡蛋";
}
}
红豆
public class RedBean extends Decorator{
/**
* 在使用ReadBean 的时候需要把 drink 传给父类
* @param drink
*/
public RedBean(Drink drink) {
super(drink);
}
/**
* 重写价格
* @return
*/
@Override
public double money() {
return super.money()+3.2;
}
/**
* 重写描述
* @return
*/
@Override
public String desc() {
return super.desc()+"+红豆";
}
}
5.测试类
public class Test {
public static void main(String[] args) {
//开始搭配
//1.创建豆浆对象(豆浆属于饮品,我们返回一个饮品)
Drink soya = new Soya();
System.out.println(soya.money()); //打印纯豆浆的信息
System.out.println(soya.desc());
//2.往纯豆浆里面加红豆
//把红豆加到豆浆里面,返回的还是饮品
Drink redBeanSoya = new RedBean(soya);
System.out.println(redBeanSoya.money()); //打印加红豆的豆浆的信息
System.out.println(redBeanSoya.desc());
//3.向红豆豆浆中加入鸡蛋
//返回的还是饮品
Drink erbs = new Egg(redBeanSoya);
System.out.println(erbs.money()); //打印相关信息
System.out.println(erbs.desc());
}
}
实际应用
Springboot中HiddenHttpMethodFilter类里面,使用HttpMethodRequestWrapper包装类来包装前端发送过来的请求,包装之后把_method返回。