策略模式

定义:

定义一系列算法,把他们各自封装成策略类,然后把不变的部分和变化的部分分离开来,其中包括策略类和环境类(Context)。

这里的算法可以理解为用于处理逻辑的方法。

使用

  1. 经典例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const strategies = {
"Q2":(s)=> s*2,
"Q3":(s)=> s*3,
"Q4":(s)=> s*4,
"Q5":(s)=> s*5
}

const calculateBouns = (name,param)=>{
return strategies[name](param);
}

console.log(calculateBouns("Q2",23));
console.log(calculateBouns("Q3",23));
console.log(calculateBouns("Q4",23));

使用calculateBouns 环境类调用对应的策略方法。

使用前先找到判断的不同点,当参数传入,共同点放在环境类里,然后根据入参值选择对应的策略方法。

而常用在一些判断规则明确的场景,如表单校验方法,根据场景选择运动算法。

以上的场景在网上都很容易找到,以下结合实际在 redux 中使用。

  1. reducer 使用策略模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 策略类
const makeTitle = (state, action)=>{
return { ...state, title: action.payload };
}

const makeTitle2 = (state, action)=>{
return { ...state, title2: action.payload };
}

let reducerMap = {};
reducerMap[actionType.PG_COMMON_TITLE] = makeTitle;
reducerMap[actionType.PG_COMMON_TITLE2] = makeTitle2;

// 环境类
export default function reducer(state,action) {
const { type } = action;
if (reducerMap.hasOwnProperty(type)) {
return reducerMap[type](state, action);
}
return state;
}

由于使用 redux 频繁时会出现switch/caseif/else,那么导致在这里函数庞大且不好理解,圈复杂度很高,但我们把 action 对应的 reduce 处理逻辑分到对应的函数里时,那么处理逻辑清晰且好维护。

  1. 在的组件的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import React, { Component } from "react";

const Input = () => {
return (
<div>
<input type="text" />
</div>
);
};

const Select = () => {
return (
<div>
<select name="a" id="a">
<option value="q">1</option>
<option value="2">3</option>
</select>
</div>
);
};

const Empty = () => {
return <div>没有选中</div>;
};

// 定义策略
const COMPONENTS = {
select: Select,
text: Input
};

// 定义环境类组件
export default class EnvComponent extends Component {
constructor(props) {
super(props);
}

render() {
const componentType = this.props.type;
const SelectedComponent = COMPONENTS[componentType] || Empty;
return <SelectedComponent {...this.props} />;
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

import React, { Component } from "react";

export default class demo extends Component {
constructor(props) {
super(props);
this.state = {
components: [
{ type: "text", value: "123" },
{ type: "select", value: "4" },
{ type: "xxx", value: "123" }
]
};
}

render() {
const { components } = this.state;
return (
<div>
{components.map((item, index) => {
return <EnvComponent key={index} {...item} />;
})}
</div>
);
}
}

策略模式在明确判断规则并且圈复杂度比较高的,可以考虑使用策略模式。

优缺点

优点:

1、利用组合、委托和多态技术和思想,可以避免多重条件选择语句;
2、将算法封装在独立的策略类里,使得易于切换,易于理解,易于扩展;
3、策略模式可以复用在系统的其他地方,从而避免重复的复制粘贴工作;
4、策略模式利用组合和委托让环境类拥有执行算法的能力,从而替代继承。

缺点:

1、程序中会增加许多策略类或者策略对象;
2、使用策略类必须要对所有的策略类算法了解清楚,否则不知道怎么选择,就是对判断规则有规律可循,那么就可以想出对应的环境类,由经过环境类选择策略类。