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>); // } }]