分享&记录:告别if else的“策略模式”

539 阅读4分钟

记录每一个学到的小知识以及自己的理解分享给大家好文章这里戳

举个例子

我们使用的app大多都有分享的功能,我们可以选择分享到不同的地方,比如微博、微信、QQ等等,虽然是同一个内容,但是分享到不同的平台就会有不同的处理方式,比如要跳转到不同的app或者直接复制链接等等。如果让你来实现这个功能,你会如何实现呢?

如果你对设计模式不熟悉,那么第一反应就是有if...else或者switch语句来进行条件判断,根据用户的不同选择而使用不同的处理方法。我们用代码简化地处理一下:

    var share = function( options ){
        if ( options === '微博' ){
            function1(){
                console.log('分享微博')
            }
        }
        if ( options === '微信' ){
            function2(){
                console.log('分享微信')
            }
        }
        if ( options === 'QQ' ){
            function3(){
                console.log('分享QQ')
            }
            
        }
    };

    share( '微博'); // 输出:分享微博
    share( '微信'); // 输出:分享微信

如果只是写一个这么简单的功能,那么这样的代码也未尝不可,因为这样的代码量不多,后续也不需要怎么拓展和修改,维护起来也不算麻烦。但是,我们工作中遇到的都是一些比较复杂的项目,要保证项目的可读性、可维护性和可拓展性,就必须在代码上下功夫了。

针对上面的问题,这里我们就要提到一个概念,那就是设计模式了。设计模式是指针对软件开发过程中重复发生的问题的解决办法。

今天我们就谈谈可以优化以上问题的设计模式,策略模式(Strategy Design Pattern)。

策略模式(Strategy Design Pattern)

什么是策略模式

策略这个词应该怎么理解,打个比方说,我们去逛商场,商场现在正在搞活动,有打折的、有满减的、有返利的等等,其实不管商场如何进行促销,说到底都是一些算法,这些算法本身只是一种策略,并且这些算法是随时都可能互相替换的,比如针对同一件商品,今天打八折、明天满100减30,这些策略间是可以互换的。

策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。

一个基于策略模式的程序至少由两部分组成。

第一个部分是Strategy 一组策略类,策略类封装了具体 的算法,并负责具体的计算过程。

第二个部分是环境类Context,Context接受客户的请求,随后把请求委托给某一个策略类。要做到这点,说明 Context中要维持对某个策略对象的引用。

策略模式的实现并不复杂,关键是如何从策略模式的实现背后,找到封装变化、委托和多态性这些思想的价值。

介绍到这里,相信你对策略模式有了初步的认识,用策略模式来重构前面的代码,让你加深对策略模式的理解。

// 定义Strategy类
var shareWeChat = function () {};
shareWeChat.prototype.share = function () {
  console.log("分享微信");
};
var shareQQ = function () {};
shareQQ.prototype.share = function () {
  console.log("分享QQ");
};
var shareSina = function () {};
shareSina.prototype.share = function () {
  console.log("分享微博");
};

//接下来定义Context类:
class Context {
  constructor(options, strategy) {
    this.options = options; // 设置分享的类型
    this.strategy = strategy; // 设置分享的类型对应的策略
  }
  share() { // 分享
    this.strategy.share();
  }
}

class Share {
  constructor() {
    this.algs = [];
    this.algs.push(new Context("微信", new shareWeChat() ));
    this.algs.push(new Context("微博", new shareSina() ));
  }
  shareOptions(options) {
    for (let context of this.algs) {
      if (context.options === options) {
        context.share();
      }  
    }
  }
}
var share = new Share();
share.shareOptions('微信');  // 输出: 分享微信

策略模式不仅仅可以优化if else代码,其主要的作用还是解耦策略的定义、创建和使用,控制代码的复杂度,让每个部分都不至于过于复杂、代码量过多。除此之外,对于复杂代码来说,策略模式还能让其满足开闭原则,添加新策略的时候,最小化、集中化代码改动,减少引入 bug 的风险。

与状态模式的区别

策略模式只是条件选择方法,只执行一次方法,而状态模式是随着状态的改变不停地更改执行方法。举个例子,就好比我们旅游,对于策略模式我们只需要选择其中一种出行方法就好了,但是状态模式不一样,可能我们到了A地点选择的是火车,到了B地点又选择飞机,根据不同的状态选择不同的出行方式。