设计模式 - 去除if else 的策略模式
-
前端项目中丑陋冗长的if else
if (str.includes("LonglinA")) { routers(LonglinA) } else if (str.includes("LonglinB")) { routers(LonglinB) } else if (str.includes("LonglinC")) { routers(LonglinC) } else if (str.includes("LonglinD")) { routers(LonglinD) } else if (str.includes("TaohuajiangA")) { routers(TaohuajiangA) } else if (str.includes("TaohuajiangB")) { routers(TaohuajiangB) } else { main() } // 跳转到哪个页面 function routers(e) { new Vue({ router, store, mounted() { store.commit('SET_SIDEBAR_TYPE', Vue.ls.get(SIDEBAR_TYPE, true)) store.commit('TOGGLE_THEME', Vue.ls.get(DEFAULT_THEME, config.navTheme)) store.commit('TOGGLE_LAYOUT_MODE', Vue.ls.get(DEFAULT_LAYOUT_MODE, config.layout)) store.commit('TOGGLE_FIXED_HEADER', Vue.ls.get(DEFAULT_FIXED_HEADER, config.fixedHeader)) store.commit('TOGGLE_FIXED_SIDERBAR', Vue.ls.get(DEFAULT_FIXED_SIDEMENU, config.fixSiderbar)) store.commit('TOGGLE_CONTENT_WIDTH', Vue.ls.get(DEFAULT_CONTENT_WIDTH_TYPE, config.contentWidth)) store.commit('TOGGLE_FIXED_HEADER_HIDDEN', Vue.ls.get(DEFAULT_FIXED_HEADER_HIDDEN, config.autoHideHeader)) store.commit('TOGGLE_WEAK', Vue.ls.get(DEFAULT_COLOR_WEAK, config.colorWeak)) store.commit('TOGGLE_COLOR', Vue.ls.get(DEFAULT_COLOR, config.primaryColor)) store.commit('SET_TOKEN', Vue.ls.get(ACCESS_TOKEN)) store.commit('SET_MULTI_PAGE', Vue.ls.get(DEFAULT_MULTI_PAGE, config.multipage)) }, render: h => h(e), }).$mount('#app') }
这个代码如果新增加一个需求就要新增加一个else if。那么这样十分的丑陋,那么我们是否有一个好的方法来改变他呢?如果可以,我会用设计模式中的策略模式。
策略模式
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
在这里我们可以把这里的比较方法封装一下,让它可以随意替代。
const stateList = [
{
value: "LonglinA",
str: LonglinA,
},
{
value: "LonglinB",
str: LonglinB,
},
{
value: "LonglinC",
str: LonglinC,
},
{
value: "LonglinD",
str: LonglinD,
},
{
value: "TaohuajiangA",
str: TaohuajiangA,
},
{
value: "TaohuajiangB",
str: TaohuajiangB,
},
{
value: "TaohuajiangC",
str: TaohuajiangC,
},
{
value: "TaohuajiangD",
str: TaohuajiangD,
},
]
由上面的if else的比较逻辑可以总结出:这里比较的都是str是否含有这些字符串,然后跳转到对应页面
所以最终改进的方案就是遍历封装的策略数组,然后跟传入的str进行比对,最后完成策略就执行策略的方法(或者执行默认方法)
function getStateLabel(systemParam = [], value) {
let stop = true;
systemParam.map(item => {
if (value.includes(item.value)) { // 进行策略对比
stop = false
return routers(item.str) // 执行策略方法
}
})
return stop ? main() : ''
}
所以透过现象看本质就是抽取出冗长if else 中的比较方法,进行封装。