JavaScript用策略模式消除if else 和 switch


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.可互相替換
客戶端可以在運行時選擇使用哪個算法,而且算法可以進行替換,所以客戶端依賴於策略接口。

據此,可以推斷出策略模式的使用場景:

  1. 針對同一問題的多種處理方式,僅僅是具體行為有差別時;
  2. 需要安全地封裝多種同一類型的操作時;
  3. 同一抽象類有多個子類,而客戶端需要使用 if-else 或者 switch-case 來選擇具體子類時。

策略模式的優缺點
優點

  1. 易於擴展,增加一個新的策略只需要添加一個具體的策略類即可,基本不需要改變原有的代碼,符合開放封閉原則
  2. 避免使用多重條件選擇語句,充分體現面向對象設計思想
  3. 策略類之間可以自由切換,由於策略類都實現同一個接口,所以使它們之間可以自由切換
  4. 每個策略類使用一個策略類,符合單一職責原則
  5. 客戶端與策略算法解耦,兩者都依賴於抽象策略接口,符合依賴反轉原則
  6. 客戶端不需要知道都有哪些策略類,符合最小知識原則

缺點

  1. 策略模式,當策略算法太多時,會造成很多的策略類
  2. 客戶端不知道有哪些策略類,不能決定使用哪個策略類,這點可以考慮使用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>);
// }
}]

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM