设计模式——装饰者模式
1 现状
现有已经在线上运行的“吃鸭”业务代码,先声明Eat接口,再用EatDuck类实现Eat接口,最后通过Client初始化EatDuck实例,再调用该实例的eatFood方法实现吃鸭。
1.1 定义吃的接口
package com.design.patterns.adapter;
public interface Eat {
/**
* 吃东西是共性方法
*/
void eatFood();
}
1.2 吃鸭是专门的实现
package com.design.patterns.adapter;
public class EatDuck implements Eat {
@Override
public void eatFood() {
// 吃鸭是独有的实现
System.out.println("我在吃鸭");
}
}
1.3 调用吃鸭业务代码
package com.design.patterns.adapter;
public class Client {
public static void main(String[] args) {
new EatDuck().eatFood();
}
}
2 问题
“吃鸭”的业务在线上运行良好,但是某天leader找到你说,在吃鸭前你需要洗手、蘸酱等流程。
最简单的方式,莫过于在原来的EatDuck类的eatFood方法中耦合洗手、蘸酱的代码,以快速满足需求。如下:
package com.design.patterns.adapter;
public class EatDuck implements Eat {
@Override
public void eatFood() {
System.out.println("我在洗手");
System.out.println("我在蘸酱");
// 吃鸭是独有的实现
System.out.println("我在吃鸭");
}
}
但是EatDuck类的eatFood还被多处业务引用,有的引用处只需要“吃鸭”操作就好,而不想你改动原有的实现,且leader也不想你的代码耦合度太高。
怎么办?怎样才能在不修改EatDuck类的基础上,实现洗手、蘸酱的功能呢?
思考有没有可能将吃鸭、洗手、蘸酱通过一个适配器连接在一起。
3 尝试做法
3.1 旧有代码不变
3.2 定义抽象动作类
package com.design.patterns.adapter;
public abstract class Action implements Eat{
protected Eat eat;
public Action(Eat eat){
this.eat=eat;
}
}
3.3 洗手实现动作类
package com.design.patterns.adapter;
public class WashAction extends Action{
public WashAction(Eat eat){
super(eat);
}
@Override
public void eatFood() {
System.out.println("我在洗手");
eat.eatFood();
}
}
3.4 蘸酱动作实现类
package com.design.patterns.adapter;
public class DipAction extends Action{
public DipAction(Eat eat){
super(eat);
}
@Override
public void eatFood() {
System.out.println("我在蘸酱");
eat.eatFood();
}
}
3.5 客户端调用
package com.design.patterns.adapter;
public class Client {
public static void main(String[] args) {
new WashAction(new DipAction(new EatDuck())).eatFood();
}
}
3.6 运行结果