1.背景
为什么想介绍下策略模式,因为我已经在很多场景下用到锅这个模式,相信很多人也是,这是java设计模式中非常常用的一个模式了。
2.策略模式介绍
1.什么是策略模式
策略模式就是定义一系列算法,把他们一个一个封装起来,并且使他们可以相互替换.
用人话来举个例子:就是你想去旅游,预算10w元,四个旅游团分别给出了四种方案(策略),你可以任意选择其中一个来获得不一样的旅游体验。
2.策略模式的作用
举个例子吧:
一天老板除了个需求,我要用户按照不同的会员等级获得不一样的购物体验。
程序员小菜一听,这简单啊,于是分分钟写下了下边的代码。
public void shop(User user) {
if (user.getType() == 1) { // 普通用户
// 此处省略500行
} else if (user.getType() == 2) { // vip
// 此处省略500行
} else if (user.getType() == 3) { // svip
// 此处省略500行
} else {
// 此处省略500行
}
}
程序员大鸟眉头一皱,发现事情并不简单。提出了自己的意见,这里的代码看起来好臃肿,购物的逻辑太复杂了,500行;以后又多了ssvip,sssvip可咋整呀。
小菜一听觉得很有道理,向大鸟取经。
大鸟眉头一皱,沉思片刻。发现事情很简单,你去看看策略模式吧!
3.策略模式
小菜听了大鸟的建议,去看了策略模式,并对以上述购物使用策略模式对代码进行了重构,如下。
第一步:定义购物策略的接口ShopStrategy
public interface ShopStrategy {
void shop();
}
第二步:定义具体的购物策略实现类
public static class CommonStrategy implements ShopStrategy {
@Override
public void shop() {
System.out.println("common shop");
}
}
public static class VipStrategy implements ShopStrategy {
@Override
public void shop() {
System.out.println("vip shop");
}
}
public static class SvipStrategy implements ShopStrategy {
@Override
public void shop() {
System.out.println("svip shop");
}
}
第三步:定义策略的环境类,将所有的实现类在map中维护起来方便使用
public static class ShopStrategyParse {
public Map<Integer, ShopStrategy> strategies = new HashMap<>();
public ShopStrategyParse() {
strategies.put(1, new CommonStrategy());
strategies.put(2, new CommonStrategy());
strategies.put(3, new CommonStrategy());
}
public void shop(User user) {
ShopStrategy shopStrategy = strategies.get(user.type);
shopStrategy.shop();
}
}
第四步:使用方式,直接使用环境类,传入用户即可获取到对应的购物策略
public static void main(String[] args) {
User user = new User(1); // 普通用户
ShopStrategyParse strategyParse = new ShopStrategyParse();
strategyParse.shop(user);
}
小菜的购物需求使用策略模式已经重构完毕。
emmmm,看起来代码变的更多更复杂了的样子。其实并非是这样,代码的结构变得更加清晰了,后续的维护改造和加需求也会变得方便起来,用过就知道!
4.Spring与策略模式
值得一提的是,现在使用SpringBoot框架的相对较多,在使用Spring的时候,创建环境类的时候可以使用注入的方式将所有的实现类一把注入进去,改动如下:
第一步:修改下接口定义,将策略和类型对应起来
public interface ShopStrategy {
int getId();
void shop();
}
第二步:直接在构造器中注入List,即可注入所有的实现类,方便不~
@Autowired
public ShopStrategyParse(List<ShopStrategy> shopStrategyList) {
strategies.forEach(strategy -> strategies.put(strategy.getId(), strategy));
}
这样在spring中使用策略模式就完成了。
5.总结
就个人的经验来说,策略模式特别适合改造多if-else且其中的逻辑非特别简单的场景,这种时候无论if-else还是switch都不是很好,使用策略模式会让你的代码更加的优雅,逻辑更加清晰。