• 设计模式(二):构造器模式与模块模式


    这一篇主要讲述构造器(Constructor)模式和模块(Module)模式以及相关的变体模式,例子是JavaScript代码。

    构造器(Constructor)模式

    对象构造器用于创建特定类型的对象——准备好对象以备使用,同时接收构造器可以使用的参数,以在第一次创建对象时,设置成员属性和方法的值。概念并没什么好说的,这种模式最是简单,虽然名字是那么吊炸天,但内容没什么,看下面例子就可明白。

    基本构造器

    function Car( model, year, miles ) {
      this.model = model;
      this.year = year;
      this.miles = miles;
      this.toString = function () {
        return this.model + " has done " + this.miles + " miles";
      };
    }
    // Usage:
    // We can create new instances of the car
    var civic = new Car( "Honda Civic", 2009, 20000 );
    var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
    // and then open our browser console to view the
    // output of the toString() method being called on
    // these objects
    console.log( civic.toString() );
    console.log( mondeo.toString() );

    PS:类与对象实例效果图。

    带原型的构造器

    function Car( model, year, miles ) {
      this.model = model;
      this.year = year;
      this.miles = miles;
    }
    // Note here that we are using Object.prototype.newMethod rather than
    // Object.prototype so as to avoid redefining the prototype object
    Car.prototype.toString = function () {
      return this.model + " has done " + this.miles + " miles";
    };
    // Usage:
    var civic = new Car( "Honda Civic", 2009, 20000 );
    var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
    console.log( civic.toString() );
    console.log( mondeo.toString() );

    PS:类与对象实例效果图。

    两者区别

    这两个示例区别就在于toString方法的定义。前一个例子每一个实例都各自重新定义这种方法;后一个例子使用原型定义方式,使得这种方法在所有的Car实例之间共享,好处在于,共享函数能够减少内存消耗(我认为),优化代码。

    这里需要注意几件事:

    1. 函数才有prototype属性,指向的是一个实例对象(不是函数)。

    2. 每个实例对象都有__proto__的属性,这个属性指向原函数所指的原型对象(原型继承的基础)。

    模块(Module)模式

    模块模式是为类提供私有变量和特权方法(有权访问私有变量和私有函数的公有方法)的方法。在JavaScript,就可通过闭包的方式,模拟实现模块模式。

    对象字面量:

    var myModule = {
        variableKey: variableValue,
        getKey: function () {
          // ...
        }
    };

    严格上讲,对象字面量实现的只是不完整的模块模式,因为无法达到变量、方法私有效果。不过确实有分离和组织代码的能力,也就算一种简略的模块模式的实现方式。

    简单例子:

    var myModule = (function(){
        var privateVar = 10;
        return {
            getPrivateVar : function(){
                 return privateVar;
            }
        }
    })();

    引入全局变量例子:

    // Global module
    var myModule = (function ( jQ, _ ) {
        function privateMethod1(){
            jQ(".container").html("test");
        }
        function privateMethod2(){
          console.log( _.min([10, 5, 100, 2, 1000]) );
        }
        return{
            publicMethod: function(){
                privateMethod1();
            }
        };
    // Pull in jQuery and Underscore
    })( jQuery, _ );

    PS:书中还有相应结合Dojo、ExtJS、YUI、jQuery等框架的模块模式的实现方式,不过我觉得只要理解模块模式的就行了,也不一一列例子。

    揭示(Revealling)模块模式

    这种是模块模式的改进版本,它是在模块代码底部,定义所有对外公布的函数(仅是指针)和变量。

    var myRevealingModule = (function () {
            var privateVar = "Ben Cherry",
                publicVar = "Hey there!";
            function privateFunction() {
                console.log( "Name:" + privateVar );
            }
            function publicSetName( strName ) {
                privateVar = strName;
            }
            function publicGetName() {
                privateFunction();
            }
            // Reveal public pointers to
            // private functions and properties
            return {
                setName: publicSetName,
                greeting: publicVar,
                getName: publicGetName
            };
      })();

    这种模式我经常使用,它很容易指出哪些函数和变量可以被公开访问,增强了可读性。

    总结

    有时我们在不经意间就使用了某种模式(例如上面两种模式),但并不知道写的东西已经是前人总结很好的东西了。所以在细细阅读过程中,书中内容使得我自己对模式的认识更加系统全面,也能改正自己使用上的误区。

    参考文献

    1. 《Learning JavaScript Design Patterns》 by Addy Osmani

    https://addyosmani.com/resources/essentialjsdesignpatterns/book/

    2. 《JavaScript设计模式》by 徐涛【译】

    本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。

    本文地址 :http://www.cnblogs.com/lovesong/p/5572568.html

  • 相关阅读:
    HTML5 Video/Audio播放本地文件
    jquery 美化弹出提示 漂亮的Dialog 对话框
    JavaScript中变量、作用域、内存问题
    利用nethogs查看哪些进程占用网络带宽
    Dell服务器硬件监控,使用omreport出现object not found 错误解决
    filebeat收集nginx的json格式日志
    利用logrotate切割nginx的access.log日志
    Linux下单机部署ELK日志收集、分析环境
    linux开启Rsyslog服务收集日志
    mysql占用磁盘IO过高的解决办法
  • 原文地址:https://www.cnblogs.com/lovesong/p/5572568.html
Copyright © 2020-2023  润新知