工厂模式的寄生构造模式在技术上有多么不同

Mah*_*aha 5 javascript design-patterns factory-pattern

Parasitic Constructor Pattern可以看作是工厂和构造函数模式的组合.在工厂模式中,我们调用一个函数,然后显式创建一个对象,并向对象添加所需的属性和方法,最后返回该对象.

function createPerson(name, age, job){
    var o = new Object();   //explicit object creation
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
            alert(this.name);
        };
    return o;
}

var person1 = createPerson(“Nicholas”, 29, “Software Engineer”);
var person2 = createPerson(“Greg”, 27, “Doctor”);
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • 创建并返回显式对象
  • 方法和属性将添加到显式创建的对象中
  • 没有new运算符的方法被调用

缺点:它不允许识别对象的类型.

通过使用new运算符调用任何函数都可以将其视为构造函数.当没有new操作符调用时,在函数内部,this对象指向全局对象(window在浏览器中).当使用new运算符调用函数时,它首先创建新实例,object然后将this对象设置为新创建的对象.

构造函数模式向this对象添加方法和属性,最后返回this对象,从而允许稍后使用instanceOf运算符标识对象的类型.

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
            alert(this.name);
        };
    }

    var person1 = new Person(“Nicholas”, 29, “Software Engineer”);
    var person2 = new Person(“Greg”, 27, “Doctor”);
Run Code Online (Sandbox Code Playgroud)

注意事项:

  • 使用new运算符调用函数(使JavaScript引擎将其视为构造函数)
  • 对象未显式创建,而是this返回对象

现在Parasitic Constructor Pattern显式创建并返回一个类似于工厂模式的对象,并使用new运算符调用构造函数模式:

function Person(name, age, job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
            alert(this.name);
        };
    return o;
}

var friend = new Person(“Nicholas”, 29, “Software Engineer”);
friend.sayName(); //”Nicholas”
Run Code Online (Sandbox Code Playgroud)

但是,我无法看到使用new运算符调用该函数.我的意思是,因为函数显式创建并返回对象,所以我们无法使用instanceOfoperator 显式地标识对象类型.

那么Parasitic Constructor模式有什么好处呢?是否有任何可以被利用或适用于特定对象创建场景的技术细微之处?或者只是另一种可能的编程方法来创建对象?

Ven*_*oth 1

我认为从你的角度来看,没有太大区别,但是如果你更进一步并实现抽象工厂模式,或者你开始对工厂进行多态化,那么每次编写新的工厂时,你都可以节省大量工作一。

\n\n

在 javascript 中,由于该语言没有私有值,因此您可以为对象设置任何值,因此如果您使用支持对象 OOP 标准的框架,工厂可以非常强大,并且可以从基类继承大部分逻辑。

\n\n

编辑

\n\n

好吧,在我看来,当涉及到 JavaScript 和这些模式时,最重要的一件事就是原型设计。

\n\n

原型设计基本上是在 javascript 中定义对象的方式,因此运行时实际上可以识别该对象并可以将其与其他对象区分开来。

\n\n

基本上只使用原型看起来像这样:

\n\n
var Person = function(name){\n    this.name = name\n}; //constructor\nPerson.prototype.constructor = Person;\nPerson.prototype.name = \'Dave\';\nPerson.prototype.getName = function() {\n    return this.name;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

一些测试代码:

\n\n
var dave = new Person(\'Dave\');\nconsole.log(dave.getName());\xe2\x80\x8b\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后是一个工厂:

\n\n
var PersonFactory = function(name) {\n    return new Person(name);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,该注释的问题通常是它的可维护性很差并且没有继承性。

\n\n

现在大多数框架的目的是:\n您可以创建构建原型的辅助函数,甚至构建原型链。基本上,您定义一个接受另一个对象的对象,并将其他对象成员解析为所需类对象的原型,从而为继承等留下了各种可能性。

\n\n

一些示例可以在这里找到:\n http://www.ruzee.com/blog/2008/12/javascript-inheritance-via-prototypes-and-closures

\n\n

我喜欢 mootools 处理类的方式:

\n\n
var MyClass = new Class({\nExtends: MyOtherClass\nImplements: [MyInterface, MyOtherInterface],\n\nmyPublicValue: null,\nmyOtherValue: null,\n\n\ninitialize: function() {\n    //constructor\n},\n\ndoStuff: function() {\n    return \'stuff done\';\n}\n\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

mootools 类系统本身的缺点:\n-Closure 编译器不喜欢尾随逗号,您倾向于将它们留在代码中

\n\n

-几乎没有 IDE 支持 mootools 类的自动完成(因为原型没有在文件中注释,可以使用脚本将类解析为原型文件来解析)

\n\n

现在有了这个,您可以选择大量的设计决策,让您的工厂从您自己的原型辅助类继承,使用原型辅助类来创建实际的工厂(这里有一些递归),您可以在创建时解析每个对象(类似于延迟加载)或解析页面加载时的每个类对象(请小心,如果您进入继承,在大多数实现中,您派生的类必须首先解析)\也不采取任何可能的方式。

\n\n

我希望这对你有帮助:)

\n\n

(抱歉我现在的英语不好,我今晚很累xD)

\n