引言
在物联网中,设备的控制属于基础服务,通常由专门的团队负责,业务方无需插手。然而,随着设备功能的日益复杂,简单的指令组合已经无法满足需求,业务方不得不介入维护指令下发。
随着云端和设备协议的变更,出现了多种控制方式,如全属性控制、单属性控制、新旧协议拆分控制和指令顺序控制等。因此,指令下发的逻辑也变得多样化。为了支持这些需求,业务方通常会暴露一个API,用于接收上游指令,比如场景控制和第三方调用。最初,业务方在一个简单的 control 方法中使用 if-else 语句进行维护,但随着设备品类的增加和协议的变更,这个方法变得越来越臃肿,维护起来非常困难且容易出错。
在这种背景下,能否针对不同的品类或协议实现单独维护,降低变更导致异常的风险呢?接下来,我们将通过一个示例介绍如何使用策略模式优化控制逻辑。
使用策略模式优化
经过业务分析,可以将原有的控制逻辑分成多个控制策略。在本示例中,我们将其命名为:BgControlStrategy、JZControlStrategy 和 NormalControlStrategy。
如上图所示,将原来的 control() 方法拆分成了三种控制策略。如果以后有新的控制策略,可以横向扩展。如果需要修改某个控制策略,也无需担心对其他控制逻辑的影响,满足了开闭原则。在 ControlStrategy 接口中定义了两个抽象方法,分别是控制方法和策略的优先级。
public interface ControlStrategy {
/**
* 设备控制
* @param req
* @return
*/
ControlResponse control(ControlParam req);
/**
* 返回策略优先级,数据越小优先级越高
* 默认最大值,是通用逻辑
* @return
*/
Integer order();
}
定义一个抽象类 AbstractControlStrategy,在实现 ControlStrategy 接口的基础上增加了一些所有控制类都需要使用的公共方法。
public abstract class AbstractControlStrategy implements ControlStrategy {
@Override
public Integer order() {
// 排序值默认给100
return 100;
}
// 定义一个抽象方法,用于判断该走哪个控制方法
public abstract boolean support(ControlParam req);
protected void addSceneLog(ControlParam data, ControlResponse response) {
// 记录日志
}
// 堆代码 duidaima.com
// 判断是否控制超时
protected boolean checkOfflineAndTimeout(ControlResponse res) {
// 具体实现
}
}
具体的控制类JzControlStrategy。
public class JzControlStrategy extends AbstractControlStrategy {
@Override
public Integer order() {
// 优先控制
return 1;
}
@Override
public boolean support(ControlParam req) {
// 判断是否支持该请求
if (/* 条件 */) {
return true;
}
return false;
}
@Override
public ControlResponse control(ControlParam req) {
return jzControl(req);
}
/**
* 设备控制方法
*
* @param req
* @return
*/
public ControlResponse jzControl(@Valid ControlParam req) {
// 具体控制逻辑
}
}
其他的控制类结构与之类似。最后是选择策略的入口工厂 ControlStrategyFactory。
@Service
public class ControlStrategyFactory implements InitializingBean {
// 将所有的控制策略注入成一个list
@Autowired
private List<AbstractControlStrategy> abstractControlStrategies;
// 对list按照order从小到大进行排序
@Override
public void afterPropertiesSet() throws Exception {
abstractControlStrategies.sort(Comparator.comparing(AbstractControlStrategy::order));
}
// 通过入参,按照顺序,判断本次使用哪个控制策略
public ControlStrategy getStrategy(ControlParam req) {
// 遍历控制策略类
for (AbstractControlStrategy strategy : abstractControlStrategies) {
if (strategy.support(req)) {
return strategy;
}
}
return abstractControlStrategies.get(abstractControlStrategies.size() - 1);
}
}
小结
通过使用策略模式,我们将原本臃肿的 control 方法拆分成多个独立的控制策略类,每个类负责一种具体的控制逻辑。这种方式不仅提高了代码的可维护性和可扩展性,还降低了变更导致异常的风险。策略模式的引入使得代码结构更加清晰,符合开闭原则,为后续的功能扩展和维护提供