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”);
注意事项:
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”);
注意事项:
new
运算符调用this
对象现在,寄生构造函数模式显式创建并返回一个类似于工厂模式的对象,并使用类似构造函数模式的新运算符调用它:
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
运算符显式地标识对象类型。
那么Parasitic Constructor模式的优点是什么?是否有任何可以被利用或适用于特定对象创建场景的技术细微之处?或者只是另一种可能的编程方法来创建对象?
答案 0 :(得分:3)
我认为你正在跳过工厂的那部分,就是在大多数其他语言中,工厂要么会制作多种不同类似的对象,要么就像这样:
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");
如果你有一个像制作一个对象一样简单的工厂,设置它的属性并返回对象,那么确实没有区别。
当您谈论使用大量专用组件来使某些东西聚集在一起时(无论它们是注入还是硬编码),或者您正在处理继承,这些差异就会发挥作用。
老实说,我建议在进一步研究不同的方法之前,先了解这些事情(对象组成和继承)。
因为最终,它对完成的代码没有任何影响,如果您使用了工厂,或者您使用了修改通用对象的函数,或者您刚刚在中间使用了很多类你的代码......程序会运行得很好,或者会以你切片的方式死掉。
它确实会对您的代码组织方式以及如何编写代码产生影响 如果你所做的只是在页面上按一个按钮,你真的不需要工厂 如果你在你的页面上制作一个功能齐全的MP3播放器,它需要6个按钮,一个播放列表,一个进度条和一个轨道名称,艺术家名称和封面艺术的显示......
...现在是开始研究工厂模式以确定如何将这些部件放在一起,要求一件事,然后让它从成品线上吐出成品的好时机。
答案 1 :(得分:1)
我认为从您的角度来看,没有太大区别,但如果您更进一步实施抽象工厂模式,或者您开始对工厂进行多态化,那么每次编写时都可以节省大量工作一个新的。
在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的问题通常在于它的可维护性很差,并且没有继承。
现在大多数框架都出现了: 您可以创建帮助函数来构建原型甚至构建原型链。基本上你定义了一个接受另一个对象的对象,它将其他对象成员解析为所需类对象的原型,留下了各种继承的可能性等。
可以在这里找到一些例子: http://www.ruzee.com/blog/2008/12/javascript-inheritance-via-prototypes-and-closures
我喜欢mootools处理课程的方式:
var MyClass = new Class({
Extends: MyOtherClass
Implements: [MyInterface, MyOtherInterface],
myPublicValue: null,
myOtherValue: null,
initialize: function() {
//constructor
},
doStuff: function() {
return 'stuff done';
}
});
mootools类系统本身的缺点: -Closure编译器不喜欢尾随逗号,你倾向于将它们留在你的代码中
- 几乎没有IDE支持mootools类的自动完成(因为原型不是 在文件中注释,可以使用脚本解析您的类到原型文件)
现在有了大量的设计理念,让你的工厂继承你自己的原型助手类,使用原型助手类来创建实际的工厂(这里有一些递归),你可以解决每个对象在它的创建(延迟加载)或解析页面加载上的每个类对象(小心,如果你进入继承,在它的大多数实现中,你必须首先解析你派生的类) 或以任何可能的方式。
我希望这有助于:)
(对不起我现在的英语不好,今晚很累啊xD)