• 设计模式中策略模式的实际场景运用
  • 发布于 2个月前
  • 142 热度
    0 评论
引言
在物联网中,设备的控制属于基础服务,通常由专门的团队负责,业务方无需插手。然而,随着设备功能的日益复杂,简单的指令组合已经无法满足需求,业务方不得不介入维护指令下发。

随着云端和设备协议的变更,出现了多种控制方式,如全属性控制、单属性控制、新旧协议拆分控制和指令顺序控制等。因此,指令下发的逻辑也变得多样化。为了支持这些需求,业务方通常会暴露一个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 方法拆分成多个独立的控制策略类,每个类负责一种具体的控制逻辑。这种方式不仅提高了代码的可维护性和可扩展性,还降低了变更导致异常的风险。策略模式的引入使得代码结构更加清晰,符合开闭原则,为后续的功能扩展和维护提供
用户评论