跳到主要内容

策略模式

设想这种场景:一份数据可能会做不同的处理。

这种情况下,数据一般是相对不易改变的部分,这里指的是数据的结构,而非具体的数值。对数据的处理逻辑可能会经常改变。

还是那句话:在不常变和常变之间做出区分,引入中间抽象把它们隔离开。 把数据的处理提取成接口,剥离处理方法的具体实现,这种方式被成为策略模式。 最简单常见的策略模式如下

const nums = [4, 3, 0, 8, 2];

// 从小到大
nums.sort(function (a, b) {
return a - b;
});

// 从大到小
nums.sort(function (a, b) {
return b - a;
});

nums 数组提供了一个 sort 方法,具体怎么排序则由调用方自己决定,只要排序函数满足接口即可。

这样 nums 就不用提供 sortMinToMax/sortMaxToMin 等排序方法,调用方爱怎么排序就怎么排序,自己来。

策略模式还有一个很经典的应用场景:消息通信中,对不同的消息做不同的处理。

class Message {
public code;
public bytedata;
}

对消息的处理可以抽象成共同的接口:

class MsgHandler {
// 消息状态码
public codes;
public handle(msg);
}

// 消息处理的实现
class MsgHandler404 extends MsgHandler {
MsgHandler404() {
super();
this.codes = {
404,
};
}
public handle(msg) {
// ... doSomething
}
}

// 类似发布订阅,但是固定msg订阅固定事件
class Handlers {
private handlers = new Map();
// register 提供消息处理器的插拔机制
public void register(handle:MsgHandler) {
for (let i = 0; i < handler.codes.length; i++) {
code = handler.codes[i];
list = handlers.get(code);
if (list == null) {
list = [];
handlers.put(code, list);
}
list.push(handler);
}
}
// 不再使用 switch (msg.code) 的方式处理消息
public handle(msg) {
list = handlers.get(msg.code);
for (let i = 0; i < list.length; i++) {
handler = list.get(i);
// 每个handler处理一下
handler.handle(msg);
}
}
}