美文网首页
js常用的设计模式

js常用的设计模式

作者: 一二三kkxx | 来源:发表于2019-02-25 20:30 被阅读1次

    本文为阅读《js设计模式与开发实践》摘录。

    一. 单例模式

    1.定义

    保证一个类仅有一个实例,并提供一个访问它的全局访问点

    单例模式是一种常见的模式,有一些对象我们往往只需要一个,比如全局缓存,线程池等.这个时候就适合用单例模式创建.

    例子

    单例模式并不复杂,用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象.

    var Singleton = function(name){
      this.name = name
    }
    Singleton.prototype.getName = function(){
      alert(this.name)
    }
    Singleton.getInstance = (function(){
      var instance = null;
      return function(name){
          if(!instance){ // 如果instance已经有值 就用之前的值
            instance = new Singleton(name)
          }
          return instance;
      }
    })()
    var a = Singleton.getInstance('test1')
    var b = Singleton.getInstance('test2')
    console.log(a === b)
    

    二.策略模式

    定义

    在程序设计中,要实现某个功能会有多种方案可以选择.这种解决方案就是策略模式

    定义一系列算法,把他们一个个封装起来,并且使他们可以相互替换

    案例

    绩效为S的人年终奖4倍工资,绩效为A的年终奖为3倍,绩效为B的年终奖2倍

    //面向对象方式
    var performanceS = function(){};
    performanceS.prototype.calculate = function(salary){
      return salary * 4
    }
    var performanceA = function(){};
    performanceA.prototype.calculate = function(salary){
      return salary * 3
    }
    var performanceB = function(){}
    performanceB.prototype.calculate = function(salary){
      retun salary * 2
    }
    //定义奖金类
    var Bouns = function(){
      this.salary = null;
      this.strategy = null; 
    }
    Bouns.prototye.setSalary = function(salay){
      this.salary = salary;
    }
    Bouns.prototype.setStrategy = function(){
      this.strategy = strategy;
    }
    Bouns.prototype.getBouns = function(){
      return this.strategy.calculate(this.salary)
    }
    
    var bouns = new Bouns();
    bouns.setSalary(100000);
    bouns.setStrategy(new PerformanceS());
    bouns.getBouns() // 40000
    bouns.setStrategy(new PerformanceA())
    bouns.getBouns()  // 30000
    
      //js函数方法
     var strategies = {
      "S":function(salary){
        return salary * 4;
       },
      "A":function(salary){
        return salary * 3
      },
      "B":function(salary){
        return salary * 2
       }
    }
    var calculateBouns = function(level,salary){
      return strategies[level](salary)
    }
    calculateBouns('S',10000) //40000
    calculateBouns('A',10000) // 20000
    
    优点
    • 避免多重条件选择语句
    • 提供了对开放-封闭原则的支持,将算法封装在strategy中,使得他们易于切换,易于理解,易于扩展
    • 可以复用在系统的其他地方

    三.代理模式

    定义

    代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问

    代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对象,替身对象对请求做出一些处理之后,再把请求转交给本体对象

    类似买二手房,通过中介去完成交易,买家直接和中介对接.中介再和卖家对接.

    案例

    A要给M送花.M心情好的时候,成功率为60%;M心情不好的时候,成功率趋向于0;
    A和M刚认识.而A的朋友B和M关系很好,则A把花交给B,让B在M心情好的时候把花送给他

    var  Flower = function(){}
    var A = {
      sendFlower: function(target){
        var flower = new Flower();
        target.recieveFlower(flower);
      }
    }
    var B= {
      recieveFlower: function(flower){
        M.listenGoodMood(function(){
           M.recieveFlower(flower)
        })
      }
    }
    var M = {
      recieveFlower:function(flower){
        console.log('收到花'+ flower)
      },
      listenGoodMood:function(fn){
        setTimeout(function(){  // 假设10秒后心情变好.
          fn() 
        },10000)
      }
    }
    
    A.sendFlower(B)
    

    求乘积

    var mult = function(){
      console.log('开始计算乘积');
      var a = 1 ;
      for(var i = 0 ; i < arguments.length;i++){
        a = a * arguments[i]
      }
      return a;
    }
    var proxyMult = (function(){
      var cache = {};
      return function(){
        var args = Array.prototype.join.call(arguments,',')
        if(args in cache){
          return cache[args]
        }
        return cache[args] = mult.apply(this,arguments)
       }
    })()
    
    proxyMult (1,2,3,4);  // 开始计算乘积 24  
    proxyMult (1,2,3,4); // 24  取缓存里的值 不走mult函数了
    

    四.发布-订阅者模式

    发布-订阅者模式又叫观察者模式,他定义对象间的一种一对多的依赖关系,

    案例
    var event = {
      clientList : [],
      listen:function(key,fn){
        if(!this.clientList[key]){ // 如果没有订阅过,则给该类消息创建一个缓存列表
          this.clientList[key] = []
        }
        this.clientList[key].push(fn)  //订阅的消息添加进缓存列表
      },
      trigger:function(){
        var key = Array.prototype.shift.call(arguments), // 取出消息类型
              fns = this.clientList[key]; // 取出该消息时对应的回调函数集
        if(!fns || fns.length === 0 ){ return false;}
        for(var i = 0 ,fn;fn = fns[i++];){
          fn.apply(this,arguments)  
        }
      }
    }
    // 定义一个installEvent函数,这个函数可以给所有的对象都动态安装发布-订阅功能
    var installEvent = function(obj){
      for(var i in event){
        obj[i] = event[i]
      }
    }
    
    var salesOffices = {}
    installEvent(salesOffices)
    salesOffices.listen('squareMeter88',function(price){
      console.log(price)
    })
    salesOffices.listen('squareMeter100',function(price){
      console.log(price)
    })
    salesOffices.trigger('squareMeter88',2000000)
    salesOffices.trigger('squareMeter100',3000000)
    

    相关文章

      网友评论

          本文标题:js常用的设计模式

          本文链接:https://www.haomeiwen.com/subject/mpdwyqtx.html