zoukankan      html  css  js  c++  java
  • 前端设计模式

    1、模块模式
    在立即执行函数表达式中定义的变量和方法,在该函数外部是访问不到的,只能通过该函数提供的接口,"有限制的"进行访问;通过函数的作用域,解决了属性和方法的封装问题。
    最常见的立即执行函数写法有以下两种:

    
    (function(){ /* code */ }())
    或者
    (function(){ /* code */ })()
    

    模块模式代码:

    
        let Person = (function(){
            var age = "12";
            var name = "jerry";
            function getAge(){
                return age;
            }
            function getName(){
                return name;
            }
            return {
                getAge: getAge,
                getName: getName
            }
        })()
        console.log(age, 'age'); // 报错: Uncaught ReferenceError: age is not defined
        console.log(name, 'name'); // 空字符串,为啥不报错?看底部备注
        console.log(Person.age); // undefined
        console.log(Person.name); // undefined
        // 只能通过Person提供的接口访问相应的变量
        console.log(Person.getName()); // jerry
        console.log(Person.getAge()); // 12
    

    2、构造函数模式

    
        function Person(name,age){
            this.name = name;
            this.age = age;
        }
        Person.prototype.printName = function(){
            console.log(this.name)
        }
        Person.prototype.printAge = function(){
            console.log(this.age)
        }
        function Student(name,age){
            // 继承 Person 的属性
            Person.call(this,name,age)
        }
        function create(prototype){
            function F(){}
            F.prototype = prototype
            return new F()
        }
        // 让Student的原型指向一个对象,该对象的原型指向了Person.prototype,通过这种方式继承 Person 的方法
        Student.prototype = create(Person.prototype)
        Student.prototype.printAge = function(){
            console.log(this.age)
        }
        let student = new Student('jerry',12)
        student.printName() // "jerry"
        student.printAge() // "12"
    

    3、混合模式

    
        function Person(name,age){
            this.name = name
            this.age = age
        }
        Person.prototype.printName = function(){
            console.log(this.name)
        }
        function Student(name,age){
            // 继承 Person 的属性
            Person.call(this, name, age)
        }
        function create(prototype){
            function F(){}
            F.prototype = prototype
            return new F()
        }
        // 让Student的原型指向一个对象,该对象的原型指向了Person.prototype,通过这种方式继承 Person 的方法
        Student.prototype = create(Person.prototype)
        Student.prototype.printAge = function(){
            console.log(this.age)
        }
        let student = new Student('jerry', 12)
        student.printName() // "jerry"
        student.printAge() // 12
    

    4、工厂模式

    
        function Person(name, age){
            let person = new Object()
            person.name = name
            person.age = age
            person.printName = function(){
                console.log(this.name)
            }
            person.printAge = function(){
                console.log(this.age)
            }
            return person
        }
        let person = Person('jerry',12)
        person.printName()
        person.printAge()
    

    5、单例模式

    
        let Singleton = (function(){
            let instantiated
            function init(){
                /*定义单例代码*/
                return{
                    publicMethod: function(){
                        console.log("Hello World");
                    },
                    publicProperty: "Test"
                }
            }
            return{
                getInstance: function(){
                    if(!instantiated){
                        instantiated = init()
                    }
                    return instantiated
                }
            }
        }())
        Singleton.getInstance().publicMethod()
    

    单例之间的通讯:
    建立两个独立的对象:jim&&lily,两者之间通过door直接通讯,如果没有新建door,有直接通讯。代码如下:

    
        let jim = (function(argument){
            let door
            let jimHome = function(msg){
                this.doorbell = msg
            }
            let info = {
                sendMessage: function(msg){
                    if(!door){
                        door = new jimHome(msg)
                    }
                    return door
                },
                coming: function(){
                    return "來了來了"
                }
            }
            return info
        }())
        let lily = {
            callJim: function(msg){
                let _xw = jim.sendMessage(msg)
                alert(_xw.doorbell)
                console.log(_xw.doorbell)
                _xw = null // 等待垃圾回收
                let coming = jim.coming()
                console.log(coming)
            }
        }
        lily.callJim("叮咙")
    

    6、发布-订阅模式
    订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象。这个主题对象在自身主题变化时,会通知所有订阅者对象,使他们能够自动更新自己的状态。
    将一个系统分割成一系列相互协作的类有一个很不好的副作用:需要维护相应对象间的一致性,这样会给维护、扩展和重用都带来不便。当一个对象的改变需要同时改变其他对象,而且他不知道具体有多少对象需要改变时,此时建议使用订阅发布模式。
    应用场景:
    DOM事件。DOM事件是一种典型的发布-订阅模式,对一个DOM节点的DOM事件进行监听;当操作DOM节点时,触发相应的事件并执行函数。
    自定义时间。指定发布者,类似于一个对象(key:value);key表示事件的名称,value是一个数组;发布消息后,遍历value的数组,依次执行订阅者的回调函数。
    应用Demo如下:

    
        let 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事件,value is' + val)
        })
        Event.on('click', function(val){
            console.log('click事件,value is '+ val)
        })
        Event.fire('change', 'jerry1')
        Event.fire('click', 'jerry2')
        Event.off('change')
    

    备注:console.log(name, 'name')没有报错,是因为name是浏览器的窗口变量名,已存在于浏览器内部。

    来源:https://segmentfault.com/a/1190000018127390

  • 相关阅读:
    设计模式之组合模式
    设计模式之桥接模式
    设计模式之装饰模式
    设计模式之代理模式
    总结的一些MySQL索引相关的知识点
    软件架构设计-五视图方法论
    博客迁移
    IMDB.COM排名算法(贝叶斯公式)和Reddit评论排行算法
    利用ratchet 和 ZeroMQ 实现即时(推送)聊天的功能
    composer Ratchet 实验心得
  • 原文地址:https://www.cnblogs.com/qixidi/p/10390838.html
Copyright © 2011-2022 走看看