js程序中最常用的if else循環,如果分枝很多的的情況下難免使寫出的程序又臭又長,但是根據需求又必須將這些分支處理,此時稍有經驗的程序員可能會想到用switch case優化但是只是僅僅做到利於閱讀,最好的方法是用策略模式進行優化。
那么如何拒絕使用if else呢?
如果程序中只有一個else:
if(con){ dosomething(); }else{ dootherthings(); }
可以用如下的方法拒絕else:
if(con){ dosomething(); return; } dootherthings();
或者用三目運算符:con ? dosometing() : dootherthings();
如果程序中有多個else:
if(con1){ dothing1(); }else if(con2){ dothing2(); }else if(con3){ dothing3(); }
或者像我們系統里面這樣:
可以用策略樹實現:
var stats ={ obj1:function(){ doSomething1(); }, obj2:function(){ doSomething2(); }, obj3:function(){ doSomething3(); }, obj4:function(){ doSomething4(); }, obj5:function(){ doSomething5(); } }
調用:
function handle(obj){ stats[obj.name](); }
函數定義。

如果沒有調用方法,可以用面向對象思想,用健值對實現,比switch要簡單:


總結
使用if...else...的弊端在於:不利於對程序的擴展,如果新添加了一個顏色類型,那么就得去修改程序再添加一個if...else...分支,根據“開-閉原則”的宗旨:對擴展開,對修改閉。顯然是用if...else...已經go out了。
策略模式最開始在java用的多,使用的多態機制指:方法的重構,根據方法名相同兒參數不同的機制,來實現拒絕關鍵字。
我們將這個概念移植到javaScript也毫不違和。
真的是在前人基礎上寫switch和if else要寫吐了,沒辦法。
我們回頭再來總結一下什么是策略模式,以及策略模式的優缺點:
策略模式是oop中最著名的設計模式之一,是對方法行為的抽象,可以歸類為行為設計模式,也是oop(Object Oriented Programming,面向對象編程)中interface(接口,這塊如果有更好的解讀,歡迎評論)經典的應用。其特點簡單又實用,是我最喜歡的模式之一。策略模式定義了一個擁有共同行為的算法族,每個算法都被封裝起來,可以互相替換,獨立於客戶端而變化。
我們可以從三個方面來理解策略模式:
1.算法族
使用多種不同的處理方式,做同樣的事情,僅僅是具體行為有差別。這些處理方式,組合構成算法策略族,它們的共性,體現在策略接口行為上。
2.算法封裝
將各個算法封裝到不同的類中,這樣有助於客戶端來選擇合適的算法。
3.可互相替換
客戶端可以在運行時選擇使用哪個算法,而且算法可以進行替換,所以客戶端依賴於策略接口。
據此,可以推斷出策略模式的使用場景:
- 針對同一問題的多種處理方式,僅僅是具體行為有差別時;
- 需要安全地封裝多種同一類型的操作時;
- 同一抽象類有多個子類,而客戶端需要使用 if-else 或者 switch-case 來選擇具體子類時。
策略模式的優缺點
優點
- 易於擴展,增加一個新的策略只需要添加一個具體的策略類即可,基本不需要改變原有的代碼,符合開放封閉原則
- 避免使用多重條件選擇語句,充分體現面向對象設計思想
- 策略類之間可以自由切換,由於策略類都實現同一個接口,所以使它們之間可以自由切換
- 每個策略類使用一個策略類,符合單一職責原則
- 客戶端與策略算法解耦,兩者都依賴於抽象策略接口,符合依賴反轉原則
- 客戶端不需要知道都有哪些策略類,符合最小知識原則
缺點
- 策略模式,當策略算法太多時,會造成很多的策略類
- 客戶端不知道有哪些策略類,不能決定使用哪個策略類,這點可以考慮使用IOC容器和依賴注入的方式來解決
以上,完。最后附上我寫的一個demo的代碼。
import { Icon, WrapNo } from 'common';
import React, { Component, } from 'react';
export const stateList = [
{
value:"ON",
str: "已開啟",
iconStr:"icon-running",
colorStr:"#52C41A"
},
{
value: "OFF",
str: "已關閉",
iconStr:"icon-power-off",
colorStr:"#909090"
},
{
value: "NOT_ALLOCATED",
str: "未部署",
iconStr:"icon-power-off",
colorStr:"#909090"
},
{
value: "LOCKED",
str: "已鎖定",
iconStr:"icon-lock-circle",
colorStr:"#d36564"
},
{
value: "PAUSED",
str: "已暫停",
iconStr:"icon-pause",
colorStr:"#e0ac42"
},
{
value: "UNKNOWN",
str: "未知",
iconStr:"icon-power-off",
colorStr:"#909090"
},
{
value: "MANAGED",
str: "納管中",
iconStr:"icon-running",
colorStr:"#52C41A"
}
]
export const getStateLabel = (systemParam = [], value) => {
const result = systemParam.find(item => item.value === value)
if (result) {
return (<div><Icon color={result.colorStr} type={result.iconStr} /> {result.str}</div>)
}
return "--"
}
使用:
import {getStateLabel, stateList} from "src/utils/constant"
columns = [
{
title: '狀態',
width: 160,
//align: 'center',
dataIndex: 'state',
fixed: 'left',
render: text => getStateLabel(stateList, text),
// render: text => {
// let str = '';
// let iconStr = '';
// let colorStr = '';
// switch (text) {
// case 'ON': str = '已開啟'; iconStr = 'icon-running'; colorStr = '#52C41A'; break;
// case 'OFF': str = '已關閉'; iconStr = 'icon-power-off'; colorStr = '#909090'; break;
// case 'NOT_ALLOCATED': str = '未部署'; iconStr = 'icon-power-off'; colorStr = '#909090'; break;
// case 'LOCKED': str = '已鎖定'; iconStr = 'icon-lock-circle'; colorStr = 'rgb(211, 101, 100)'; break;
// case 'PAUSED': str = '已暫停'; iconStr = 'icon-pause'; colorStr = 'rgb(224, 172, 66)'; break;
// case 'UNKNOWN': str = '未知'; iconStr = 'icon-power-off'; colorStr = '#909090'; break;
// }
// return (<div><Icon color={colorStr} type={iconStr} /> {str}</div>);
// }
}]
