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”);
注意事项:
- 使用
操作符调用函数(使JavaScript引擎将其视为构造函数)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”
但是,我看不到使用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");
如果你有一个工厂,它就像制作一个对象、设置它的属性和返回对象一样简单,那么这真的没有什么区别
当您谈论使用大量专用组件将某些东西组合在一起(无论它们是注入的还是硬编码的)时,或者您正在处理继承时,这些差异就开始发挥作用
老实说,我建议在深入研究不同的实现方法之前,多了解这些东西(对象组合和继承)
因为它最终对完成的代码没有任何影响,如果你使用了一个工厂,或者如果你使用了一个修改了通用对象的函数,或者你在代码的中间使用了大量的类…这个程序将运行良好,或将死亡,无论你如何切片它
它真正起作用的地方在于如何组织代码,以及如何编写代码