美文网首页
常见设计模式

常见设计模式

作者: 不是我的简书 | 来源:发表于2017-06-01 18:50 被阅读18次

    混合模式、模块模式、单例模式、构造函数模式、工厂模式、发布订阅模式范例

    1.涉及继承的时候,可以使用混合模式

    function Person(name,age){
        this.name = name
        this.age = age
    }
    Person.prototype.sayName = function(){
        console.log(this.name)  
    }
    
    var Student = function(name,age,score){
        // 实例属性实现继承
        Person.call(this,name,age)  // 从Person继承name,age
        this.score = score
    }
    
    // 将Person.prototype挂在Student.prototype的原型链第一层
    // 原型链实现继承
    Student.prototype = Object.create(Person.prototype);
    Student.prototype.getName = function () {
      return this.name;
    }
    
    new Student() ==> // {name :'',age:'',score:''}
    

    2.写一个模块并封装,只暴露必需接口,可以使用模块模式

    //利用函数作用域特性,通过闭包,实现作用域的隔离来实现一个模块
    var Person =(function(){
        var name = "robin"
        function sayName(){
            console.log(name)
        }
        return{
            name:name,
            sayName:sayName,
            changeName:function(newName){
                name = newName
            }
        }
    })()
    
    Person.sayName()   //robin 
    Person.changeName("lisa")
    Person.sayName()  //lisa
    

    3.想要得到一个对象,该对象在某个作用域或场景下是独一无二的,可以使用单例模式

    //单例模式obj1=obj2,创建出的对象都是相同的,可以节约内存
    var singleModule = (function(){
        var instance;
        function init(){
            return{
    
            }
        }
        return {
            getInstance:function(){
                if( !instance){    //只有第一次调用instance内容才空,之后都不会进入该逻辑
                    instance = init();
                }
                return instance;
            }
        }     
    })()
    
    var obj1 = singleModule.getInstance()
    var obj2 = singleModule.getInstance()
    
    obj1 === obj2  //true
    

    4.构造函数模式

    //把方法绑定到函数原型上,然后通过new的形式创建对象
    
    function Person(name,age){
        this.name = name
        this.age = age
    }
    
    // 实例一个对象
    var student = new Person("robin",20)
    console.log(student)
    

    5.工厂模式
    缺点:每次都会开辟新内存

    //构造函数模式基础版
    //函数内部创建一个对象(可以是字面量方式、构造函数方式、或其它方式),再把这个对象return出来
    
    function createPerson(opts){
        var person = {
            name : opts.name ||'robin'
        }
        person.sayName = function(){
            console.log(this.name)
        }
        return person
    }
    
    var p1 = createPerson({name:'lisa'})
    p1.sayName()   //lisa
    

    6.发布订阅模式 pub/sub

    //发布订阅模式
    var EventCenter=(function(){
        var events={};    //events={evt:[{handler:fun1},{handler:fun2}]}
        function on(evt,handler){
            events[evt]=events[evt]||[];
            events[evt].push({handler:handler})
        }
        function fire(evt,args){
            if(!events[evt]){
                return;
            }
            for(var i=0;i<events[evt].length; i++){
                events[evt][i].handler(args);
            }
        }
        return {
            on:on,
            fire:fire
        }
    })()
    
    EventCenter.on('my_event',function(data){
        console.log('11111111')
    })
    EventCenter.on('my_event',function(data){
        console.log('2222222')
    })
    EventCenter.fire('my_event')
    
    var EventCenter = (function(){
      //我们如何去实现
      var F = function() {
        this.eventPool = {}; 
      };
      F.prototype.on = function(name, callback) {
        if(!this.eventPool[name]){
          this.eventPool[name] = [];
        }
        this.eventPool[name].push(callback);
      };
      F.prototype.trigger = function (name) {
        if(!this.eventPool[name]){
          this.eventPool[name] = [];
        }
        this.eventPool[name].forEach(function(fn){
          fn()
        })
      };
      return F;
    }());
    
    var e = new EventCenter();
    e.on('hello',function () {
      console.log('hello')
    }); 
    ===> 存 {'hello': [fn]}
    e.trigger('hello'); // hello
    ===> 取后执行
    

    7.观察者模式 observer

    
    $('input').change(function(){
       $('input').observers.forEach(function(observer) {
         observer();
       })
    })
    $('input').observers = []
    $('input').subscribe = function(fn) {
        this.observers.push(fn);
    };
    
    // API使用方式
    $('.input').subscribe(fn) ==> 记录日志
    $('input').subscribe(fn1) ==> 发起请求
    $('input').subscribe(fn2) ==> 改变UI
    

    观察者模式与发布订阅模式如何区分?

    observer vs pub/sub
    
    eg. $('input').change() 做三件事件
    
    pub/sub ==> 是根据topic 比如click等来执行通知
    trigger('日志') trigger('发起请求) trigger(UI')
    
    observer ==> 比如 redux.subscribe的api就是这样子
    不会对事情做区分
    ['日志','发起请求','UI'].forEach(fn)
    

    实践:使用发布订阅模式写一个事件管理器,可以实现如下方式调用

    var Event = (function(){
        var events = {};
    
        function on(evt, handler){
            events[evt] = events[evt] || [];
            events[evt].push({
                handler: handler
            })
        }
        function fire(evt, args){
            if(!events[evt]){
                return;
            }
            for(var i = 0; i < events[evt].length; i++){
                events[evt][i].handler(args);
            }
        }
        function off(evt){
            delete events[evt];
        }
    
        return {
            on: on,
            fire: fire,
            off: off
        }
    })();
    
    Event.on('change', function(val){
        console.log('change...  now val is ' + val);  
    });
    Event.fire('change', '饥人谷');   //change...  now val is 饥人谷
    Event.off('changer')
    
    Event.fire('change', 'test');   //change...  now val is test
    Event.off('change')
    Event.fire('change', 'test1');   //不会再输出
    

    相关文章

      网友评论

          本文标题:常见设计模式

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