一.业务描述
二.需要优化的点
上述发现、控制接口分别写了五个API,并且在Controller层有着大量的业务校验,然后再在Controller层调用Service层的设备发现、控制方法;这些业务校验的逻辑一模一样;
三.优化(为方便演示这个举三个语音平台的例子)
1.对不同平台的业务实现代码进行重构(图中的②)
① 将之前的三个语音接口提取为同一个策略接口命名为:(VoiceStrategyService)
public interface VoiceStrategyService { /** * @description: 语音控制API * @param: [jsonObject] * @return: com.alibaba.fastjson.JSONObject * @author: zhouhong * @date: 2023/5/18 9:34 */ JSONObject operateApi(@RequestBody JSONObject jsonObject; }
② 其他几个实现类实现 (VoiceStrategyService) 这一个接口
其他几个语音实现类实现上面的那个策略接口,每个策略实现类对应一个业务场景,实现具体的方法逻辑。
@Service @Log4j2 public class AliGenieServiceImpl implements VoiceStrategyService { @Override public JSONObject operateApi(JSONObject jsonObject { log.info("天猫精灵-设备发现/控制成功!"; return null; } }
@Service @Log4j2 public class DuerOSServiceImpl implements VoiceStrategyService { @Override public JSONObject operateApi(JSONObject jsonObject { log.info("小度-设备发现/控制成功!"; return null; } }
@Service @Log4j2 public class RokidServiceImpl implements VoiceStrategyService { @Override public JSONObject operateApi(JSONObject jsonObject { log.info("若琪-设备发现/控制成功!"; return null; } }
@Service @Log4j2 public class RokidServiceImpl implements VoiceStrategyService { @Override public JSONObject operateApi(JSONObject jsonObject { log.info("若琪-设备发现/控制成功!"; return null; } }
③ 接下来,定义一个上下文类(VoiceStrategyContext),该类持有一个策略对象,并提供一个方法用于设置策略对象
/** * @description: 语音策略上下文 * @author: zhouhong * @date: 2023/5/20 14:27 * @version: 1.0 */ public class VoiceStrategyContext { @Resource private VoiceStrategyService voiceStrategyService; private void setVoiceStrategy(VoiceStrategyService voiceStrategyService { this.voiceStrategyService = voiceStrategyService; } private JSONObject executeStrategy(JSONObject jsonObject { if (voiceStrategyService != null { return voiceStrategyService.operateApi(jsonObject; } return null; } /** * @description: 根据传过来的KEY值选择具体的策略 * @return: com.alibaba.fastjson.JSONObject * @author: zhouhong * @date: 2023/5/20 15:03 */ public JSONObject executeStrategyByKey(String key, JSONObject jsonObject { switch (key { case "aliGenie" : { this.setVoiceStrategy(new AliGenieServiceImpl(; return this.executeStrategy(jsonObject; } case "duerOS" : { this.setVoiceStrategy(new DuerOSServiceImpl(; return this.executeStrategy(jsonObject; } case "rokid" : { this.setVoiceStrategy(new RokidServiceImpl(; return this.executeStrategy(jsonObject; } default: { return null; } } } }
这个如果在下一层调用时知道自己需要调用哪个策略,那么 executeStrategyByKey( 方法可以直接忽略,具体调用如下所示:
/** * @description: 测试类 * @author: zhouhong * @date: 2023/5/20 15:06 * @version: 1.0 */ public class TextMain { public static void main(String[] args { VoiceStrategyContext voiceStrategyContext = new VoiceStrategyContext(; JSONObject jsonObject = new JSONObject(; // 天猫精灵 voiceStrategyContext.setVoiceStrategy(new AliGenieServiceImpl(; voiceStrategyContext.executeStrategy(jsonObject; // 小度 voiceStrategyContext.setVoiceStrategy(new DuerOSServiceImpl(; voiceStrategyContext.executeStrategy(jsonObject; // 若琪 voiceStrategyContext.setVoiceStrategy(new RokidServiceImpl(; voiceStrategyContext.executeStrategy(jsonObject; } }
结果:
15:12:38.477 [main] INFO com.zhouhong.designpattern.strategy.service.impl.DuerOSServiceImpl - 小度-设备发现/控制成功!
15:12:38.477 [main] INFO com.zhouhong.designpattern.strategy.service.impl.RokidServiceImpl - 若琪-设备发现/控制成功!
2.对开始那张图的 ① 进行代码提取
/** * @description: 语音控制公共方法抽取 * @author: zhouhong * @date: 2023/5/17 10:58 * @version: 1.0 */ public interface VoiceCommonApiService { /** * @description: 语音控制公共方法抽取 -- RequestBody格式 * @param: [jsonObject, platform] * @return: com.alibaba.fastjson.JSONObject * @author: zhouhong * @date: 2023/5/17 11:00 */ JSONObject voiceRequestBodyCommonApi(JSONObject jsonObject, String platform; }
/** * @description: 语音公共方法抽离 * @author: zhouhong * @date: 2023/5/17 11:00 * @version: 1.0 */ @Service @Log4j2 public class VoiceCommonApiServiceImpl implements VoiceCommonApiService { @Resource private VoiceStrategyContext voiceStrategyContext; @Override public JSONObject voiceRequestBodyCommonApi(JSONObject jsonObject, String platform { log.info("大量逻辑校验代码......"; voiceStrategyContext.executeStrategyByKey(platform, jsonObject; log.info("其他业务代码......"; return null; } }
优化完工
四.设计模式总结
1.简介
策略模式是一种行为型设计模式,它允许在运行时选择算法的行为。该模式将不同的算法封装在各自独立的策略类中,使得它们可以互相替换,而不会影响到客户端代码。
2.主要参与角色
-
抽象策略类(Strategy):定义了策略对象的接口或抽象类。它描述了算法的通用行为,可以包含算法的输入参数。
3.工作流程
-
环境对象在需要执行算法的时候,调用所持有的策略对象的方法。
-
客户端通过环境对象获取算法的结果。
客户端代码创建一个环境对象(Context)。
4.使用场景
-
避免条件语句:当代码中存在大量的条件语句用于根据不同条件执行不同的行为时,可以考虑使用策略模式来替代这些条件语句。策略模式将每种行为封装在单独的策略类中,使代码更加清晰、可维护。
-
可扩展性:策略模式提供了一种可扩展的方式,允许添加新的策略类来满足新的需求,而无需修改现有代码。这种灵活性使得策略模式在需要频繁添加新的算法或行为的情况下非常有用。
5.优缺点
优点:
- 提供了一种清晰的方式来管理不同算法的实现,并将其与客户端代码解耦。
- 策略类可以灵活地替换和扩展,不会对客户端代码造成影响。
- 提高了代码的可维护性和可读性,减少了大量的条件语句。
- 增加了类的数量,每个具体策略类都需要单独实现一个类。
五.示例代码地址
https://github.com/Tom-shushu/work-study.git 代码中的 design-pattern 项目