设计模式:策略+工厂+模板方法 混合使用
模式说明
-
策略工厂: 策略模式+工厂模式
工厂模式用来生成策略
-
模板方法
模板方法里组装策略方法
使用场景
-
策略模式
自然要求是 完成一件事情,其间有不同的业务场景区分。
-
工厂模式
这里的工厂是为了生产出策略,自然是具体实现层依赖抽象,把具体策略放到工厂里。
-
模板方法模式
这里的模板方法,封装的是策略方法。如果模板方法中有些方法不需要执行,可以在具体策略类中设置钩子。
类图一览
demo
- 定义的策略接口
public interface CoffeeMake {
void make();
}
-
策略的抽象父类
实现策略接口,并给出了模板方法
public abstract class AbstractStrategy implements CoffeeMake {
@Override
public void make() {
// 拿咖啡豆
takeBean();
// 研磨
grind();
// 萃取
extract();
// 加调料
if (checkAddMix()) {
addMix();
}
}
abstract void takeBean();
protected void grind() {
System.out.println("研磨");
}
protected void extract() {
System.out.println("萃取");
}
protected boolean checkAddMix() {
return true;
}
protected void addMix() {
System.out.println("加调料");
}
}
-
策略1
继承策略父类,需要覆盖模板方法中的个性化方法,并且有钩子的开关
public class AmericanoStrategy extends AbstractStrategy {
@Override
void takeBean() {
System.out.println("美式专用咖啡豆");
}
@Override
protected boolean checkAddMix() {
return false;
}
}
-
策略2
继承策略父类,需要覆盖模板方法中的个性化方法。
public class LatteStrategy extends AbstractStrategy {
@Override
void takeBean() {
System.out.println("拿铁专用咖啡豆");
}
@Override
protected void addMix() {
System.out.println("加奶");
}
}
-
策略工厂
利用枚举类,实现外部入参和策略对象的绑定。这里注意策略的线程安全,没有实体属性。
enum StrategyEnumFactory {
AMERICANO("美式", new AmericanoStrategy()),
LATTE("拿铁", new LatteStrategy());
private final String category;
private final AbstractStrategy strategy;
StrategyEnumFactory(String category, AbstractStrategy strategy) {
this.category = category;
this.strategy = strategy;
}
private String getCategory() {
return category;
}
private AbstractStrategy getStrategy() {
return strategy;
}
public static AbstractStrategy getStragety(String category) {
for (StrategyEnumFactory strategy : StrategyEnumFactory.values()) {
if (strategy.getCategory().equals(category)) {
return strategy.getStrategy();
}
}
throw new RuntimeException();
}
}
-
测试类
获取策略对象,然后调用策略的方法。
public class TestMix {
public static void main(String[] args) {
String input = "拿铁";
input = "美式";
AbstractStrategy stragety = StrategyEnumFactory.getStragety(input);
stragety.make();
}
}