zoukankan      html  css  js  c++  java
  • 设计模式简单工厂之我见

      最近开始学习JavaScript的设计模式。首先接触到的是简单工厂Simple Factory,有点小小的感悟。归结起来就是:明明可以 new A(),为什么偏偏要 createObject("A") 呢?

      关于简单工厂这种设计模式,网上有很多文章讲了实现思路。用JavaScript可以实现如下:

            /** 版本1:普通实现 ************************
             */
            (function v1() {
    
                // 具体类A
                function A() {
                }
    
                // 具体类B
                function B() {
                }
    
                // 对象创建函数(工厂函数)
                function createObject(tag) {
                    switch (tag) {
                        case "A":
                            return new A();
                        case "B":
                            return new B();
                        default:
                            return {};
                    }
                }
    
                // 客户代码 -----------------------------------
                var a = createObject("A");
                assert(a instanceof A);
                var b = createObject("B");
                assert(b instanceof B);
            })();

      问题来了:这里的代码明明可以 new A(),为什么偏偏要 createObject("A") 呢?

      我认为答案在于,A、B这些类可能只存在于库代码中,并没有向客户代码开放,所以客户代码根本就不能访问到这些类。

      为什么不开放呢?降低耦合度。在完成相同功能的条件下,客户代码知道得越少越好。

      于是,库代码和客户代码的这种隔离,导致只能采用间接的办法来创建库中类的实例,导出一个创建函数createObject() 就是一种很简单的途径。

      如下代码所示,库代码由变量library封装,而客户代码在client()中:

            /** 版本2:库代码与用户代码分离 ************************
             */
            (function v2() {
    
                // 库代码
                var library = (function () {
                    // 具体类A
                    function A() {
                    }
    
                    // 具体类B
                    function B() {
                    }
    
                    // 对象创建函数(工厂函数)
                    function createObject(tag) {
                        switch (tag) {
                            case "A":
                                return new A();
                            case "B":
                                return new B();
                            default:
                                return {};
                        }
                    }
    
                    return {createObject: createObject};
                })();
    
    
                // 用户代码 -----------------------------------
                (function client() {
                    var a = library.createObject("A");
    assert(utils.
    typeof(a) === "A"); var b = library.createObject("B"); assert(utils.typeof(b) === "B"); })(); })();

      注意,客户代码只能使用库library导出的标识符createObject(),再也不能直接使用具体类的标识符A、B了。A、B已经变成了内部类。

      通过引入一层间接性,把标记耦合(类A、B)降为数据耦合(参数"A"、"B"),既有效地隐藏了库代码的具体实现,又使得客户代码可以创建库中具体类的实例。

    示例中用到的工具函数:

        /**
         * Return the type of o as a string:
         *   -If o is null, return "null", if o is NaN, return "nan".
         *   -If typeof returns a value other than "object" return that value.
         *    (Note that some implementations identify regexps as functions.)
         *   -If the class of o is anything other than "Object", return that.
         *   -If o has a constructor and that constructor has a name, return it.
         *   -Otherwise, just return "Object".
         **/
        function type(o) {
            var t, c, n;  // type, class, name
    
            // Special case for the null value:
            if (o === null) return "null";
    
            // Another special case: NaN is the only value not equal to itself:
            if (o !== o) return "nan";
    
            // Use typeof for any value other than "object".
            // This identifies any primitive value and also functions.
            if ((t = typeof o) !== "object") return t;
    
            // Return the class of the object unless it is "Object".
            // This will identify most native objects.
            if ((c = classof(o)) !== "Object") return c;
    
            // Return the object's constructor name, if it has one
            if (o.constructor && typeof o.constructor === "function" &&
                (n = o.constructor.getName())) return n;
    
            // We can't determine a more specific type, so return "Object"
            return "Object";
        }
    
    // Return the class of an object.
        function classof(o) {
            return Object.prototype.toString.call(o).slice(8, -1);
        }
    
    
    function assert(predicate) {
        if (predicate) {
            try {
                throw new Error();
            } catch (e) {
                var loc = e.stack.replace(/Error
    /).split(/
    /)[1].replace(/^s+|s+$/, "");
                console.info("assert passed:" + loc);
            }
        }
        else {
            try {
                throw new Error();
            } catch (e) {
                console.log("Stack:" + e.stack);
                loc = e.stack.replace(/Error
    /).split(/
    /)[1].replace(/^s+|s+$/, "");
                console.error("assert failed:" + loc);
            }
        }
    }
    View Code
  • 相关阅读:
    3. 无重复字符的最长子串
    24. 两两交换链表中的节点
    2. 两数相加
    23. 合并K个排序链表
    synergy配置 Ubuntu作Server, Win 7作client
    ros与下位机通信常用的c++ boost串口应用
    tar
    发布里程计传感器信息
    ROS TF——learning tf
    在linux终端下打开pdf文件
  • 原文地址:https://www.cnblogs.com/xxfcz/p/5280731.html
Copyright © 2011-2022 走看看