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