Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 寄生构造函数模式和工厂模式在技术上有多大区别_Javascript_Design Patterns_Factory Pattern - Fatal编程技术网

Javascript 寄生构造函数模式和工厂模式在技术上有多大区别

Javascript 寄生构造函数模式和工厂模式在技术上有多大区别,javascript,design-patterns,factory-pattern,Javascript,Design Patterns,Factory Pattern,寄生构造函数模式可以看作是工厂模式和构造函数模式的组合。 在工厂模式中,我们调用一个函数,该函数随后显式创建一个对象,并向该对象添加所需的属性和方法,最后返回该对象 function createPerson(name, age, job){ var o = new Object(); //explicit object creation o.name = name; o.age = age; o.job = job; o.sayName = func

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

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”);
注意事项:

  • 创建并返回显式对象
  • 方法和属性被添加到显式创建的对象中
  • 方法调用时不使用
    new
    运算符
缺点:它不允许识别对象的类型

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”);
通过使用
new
运算符调用任何函数,都可以将其视为构造函数。在函数内部,在不使用
new
运算符调用时,
对象指向全局对象(
浏览器中的窗口
)。当使用
new
操作符调用该函数时,它首先创建
object
的新实例,然后将
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”);
注意事项:

  • 使用
    new
    操作符调用函数(使JavaScript引擎将其视为构造函数)
  • 对象不是显式创建的,而是返回此对象
现在,寄生构造函数模式显式创建并返回一个类似于factory模式的对象,并使用新的类似运算符的构造函数模式调用它:

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”
但是,我看不到使用
new
操作符调用函数的用途。我的意思是,由于函数显式创建并返回对象,我们将无法使用
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”);

那么寄生构造函数模式中什么是好的呢?对于特定的对象创建场景,是否存在可以利用或适当使用的技术细节?或者仅仅是创建对象的另一种可能的编程方法?

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

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

编辑

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

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

基本上,仅使用原型如下所示:

var Person = function(name){
    this.name = name
}; //constructor
Person.prototype.constructor = Person;
Person.prototype.name = 'Dave';
Person.prototype.getName = function() {
    return this.name;
}
一些测试代码:

var dave = new Person('Dave');
console.log(dave.getName());​
最后是一个工厂:

var PersonFactory = function(name) {
    return new Person(name);
}
现在,anotation的问题通常是它的可维护性差,没有继承性

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

以下是一些例子:

我喜欢mootools处理类的方式:

var MyClass = new Class({
Extends: MyOtherClass
Implements: [MyInterface, MyOtherInterface],

myPublicValue: null,
myOtherValue: null,


initialize: function() {
    //constructor
},

doStuff: function() {
    return 'stuff done';
}

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

-大多数无IDE支持mootools类的自动完成(因为原型不支持) 在文件中注释,可以使用脚本将类解析为原型文件)

现在有了它,您可以进行大量的设计决策,让您的工厂从您自己的prototype helper类继承,使用prototype helper类创建实际的工厂(这里有一些递归),您可以在创建时解析每个对象(类似延迟加载)或在页面加载时解析每个类对象(如果要进行继承,请小心,在大多数派生自的it类实现中,必须首先解析) 或者走任何可能的路

我希望这有帮助:)


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

我想你要跳过的部分是,在大多数其他语言中,工厂要么将制造多种不同类型的类似对象,无论是:

var truck = carFactory("Truck");
var jeep  = carFactory("Jeep");
var piano = instrumentFactory.piano("Grand");
var bass  = instrumentFactory.bass("Upright");
或者像这样做:

var truck = carFactory("Truck");
var jeep  = carFactory("Jeep");
var piano = instrumentFactory.piano("Grand");
var bass  = instrumentFactory.bass("Upright");
或者任何其他你想要的界面

或者工厂的责任是通过依赖注入和潜在的多态性,从较小的类中生成一个非常大的类:

function createTank (gunType) {
    var armour = new Armour();
    armour.hp  = 120;

    var wheels = new ChainTracks();

    var driver = new Soldier();
    driver.hp  = 15;

    var gun = gunFactory(gunType);

    var tank = new Tank(armour, wheels, gun);
    tank.driver = driver;

    return tank; 
}

var ground_tank = createTank("cannon");
var aa_tank = createTank("flak_cannon");
var at_tank = createTank("depleted_uranium_lancer");
如果你有一个工厂,它就像制作一个对象、设置它的属性和返回对象一样简单,那么这真的没有什么区别

当您谈论使用大量专用组件将某些东西组合在一起(无论它们是注入的还是硬编码的)时,或者您正在处理继承时,这些差异就开始发挥作用

老实说,我建议在深入研究不同的实现方法之前,多了解这些东西(对象组合和继承)

因为它最终对完成的代码没有任何影响,如果你使用了一个工厂,或者如果你使用了一个修改了通用对象的函数,或者你在代码的中间使用了大量的类…这个程序将运行良好,或将死亡,无论你如何切片它

它真正起作用的地方在于如何组织代码,以及如何编写代码