前言
工厂这个名词我们可以先分析一下,一般工厂的特点都是大批量的造东西,要是只做一个的话,倒是可以在家搭个小作坊,半年产值一个也是可以的。再有呢,工厂普遍是单一生产,哪怕是产品功能改了,那我就把流水线改一改,换几个机组,大的流程还是不变的。那如果要是,工厂今天造船,明天想造飞机,基本是没戏,造飞机和造船是完全不同的两套流程和设备,这么大的变动,不是一个工厂想改就改的。
正文:
现在正好有一个店家在卖手机,他们自己做手机自己销售,这店家就叫DayDayPhone,买手机的时候呢你告诉他一个牌子,就能买到这个牌子的手机了:
var DayDayPhone = {
sellPhone:function(brand){
var Phone;
switch (brand){
case 'Apple':
Phone = new ApplePhone();
break;
case 'Huawei':
Phone = new HuaweiPhone();
break;
default 'Xiaomi':
Phone = new XiaomiPhone();
break;
}
return Phone;
}
}
function ApplePhone(){};
function HuaweiPhone(){};
function XiaomiPhone(){};
var havePhone = DayDayPhone.sellPhone('Huawei');
这样的销售未免太单调了,所以厂家给了一次抽奖的机会,会帮你开机测试一下,只是区别是抽奖是店家的方法,开机测试呢是手机自带的功能。看起来就是这样:
var DayDayPhone = {
lottery:function (){
console.log('您已经使用了一次抽奖机会');
},
sellPhone:function(brand){
var Phone;
switch (brand){
case 'Apple':
Phone = new ApplePhone();
break;
case 'Huawei':
Phone = new HuaweiPhone();
break;
default:
Phone = new XiaomiPhone();
break;
}
this.lottery();
Phone.starting();
return Phone;
}
}
function ApplePhone(){
this.starting = function(){};
//其他方法
};
function HuaweiPhone(){
this.starting = function(){};
//其他方法
};
function XiaomiPhone(){
this.starting = function(){};
//其他方法
};
var havePhone = DayDayPhone.sellPhone('Huawei');
现在看起来一切还好啊,什么工厂什么的,提那些干什么。只是有一天店里可以卖Vivo手机了,于是店长发现了一个问题,我卖手机的流程一点没变,抽个奖,测试一下,手机就是你的了。但是一来新手机店里就要大改,主要就是生产手机的这块,能不能给它交给一个工厂,我拿到货就卖,你们工厂呢来了品牌,无非是改改流水线,很好管理。于是现在的模式就是这样了:
var DayDayPhone = {
lottery:function (){
console.log('您已经使用了一次抽奖机会');
},
sellPhone:function(){
var Phone = PhoneFactory.madePhone('Vivo');
this.lottery();
Phone.starting();
return Phone;
}
}
var PhoneFactory = {
madePhone:function(brand){
var FactoryPhone;
switch (brand){
case 'Apple':
FactoryPhone = new ApplePhone();
break;
case 'Huawei':
FactoryPhone = new HuaweiPhone();
break;
case 'Vivo':
FactoryPhone = new VivoPhone();
break;
default:
FactoryPhone = new XiaomiPhone();
break;
}
return FactoryPhone;
}
}
function VivoPhone(){
this.starting = function(){};
this.notice = function(){
console.log('我新买的Vivo手机');
}
//其他方法
};
function ApplePhone(){
this.starting = function(){};
//其他方法
};
function HuaweiPhone(){
this.starting = function(){};
//其他方法
};
function XiaomiPhone(){
this.starting = function(){};
//其他方法
};
var havePhone = DayDayPhone.sellPhone('Huawei');
havePhone.notice();//我新买的Vivo手机
现在我们稍稍改动一下,如果像现在这样,那这就是我一个人的店,要是能用一个方法,给不同的人开店该多好,我只要给我的点起个名字,用一下开店的方法,那我的店就建成了。实际上就是把上面的代码,改写成构造函数的形式:
function PhoneShop() {};
PhoneShop.prototype.lottery = function() {
console.log('您已经使用了一次抽奖机会');
};
PhoneShop.prototype.sellPhone = function(brand) {
var Phone = PhoneFactory.madePhone(brand);
this.lottery();
Phone.starting();
return Phone;
}
//以下的代码都没变
var PhoneFactory = {
madePhone: function(brand) {
var FactoryPhone;
switch(brand) {
case 'Apple':
FactoryPhone = new ApplePhone();
break;
case 'Huawei':
FactoryPhone = new HuaweiPhone();
break;
case 'Vivo':
FactoryPhone = new VivoPhone();
break;
default:
FactoryPhone = new XiaomiPhone();
break;
}
return FactoryPhone;
}
}
function VivoPhone() {
this.starting = function() {};
this.notice = function() {
console.log('我新买的Vivo手机');
}
//其他方法
};
function ApplePhone() {
this.starting = function() {};
//其他方法
};
function HuaweiPhone() {
this.starting = function() {};
//其他方法
};
function XiaomiPhone() {
this.starting = function() {};
//其他方法
};
var DayDayPhone = new PhoneShop();
var havePhone = DayDayPhone.sellPhone('Huawei');
havePhone.notice(); //我新买的Vivo手机
这样我们其实就完成了一个简单工厂。那工厂模式具体怎么表述呢,我们一会再说,首要目的是先感受一下什么是工厂模式。
上面的代码还是有点不完美,那真正的工厂模式应该是什么样的。我们继续说店长家的故事。虽然工厂被分出去了,看起来很不错很好管理。但是店长觉得这样不行,这工厂原来就是我的,现在分出去了好像跟我一点关系都没有了,而且如果以后要是开始卖平板电脑Ipad,那就是再开了一家工厂。如果像现在这样操作并不是很方便,卖东西的时候要判断顾客买的是平板还是手机:
function PhoneOrIpadShop() {};
PhoneOrIpadShop.prototype.lottery = function() {
console.log('您已经使用了一次抽奖机会');
};
//传入两个参数第一个判断是手机还是平板电脑,第二个是品牌
PhoneOrIpadShop.prototype.sellPhoneOrIpad = function(kind,brand) {
var product;
if(kind === 'Phone'){
product = PhoneFactory.madePhone(brand);
}else if(kind === 'Ipad'){
product = IpadFactory.madeIpad(brand);
}
this.lottery();
product.starting();
return product;
}
var PhoneFactory = {
madePhone: function(brand) {
var FactoryPhone;
switch(brand) {
case 'Apple':
FactoryPhone = new ApplePhone();
break;
case 'Huawei':
FactoryPhone = new HuaweiPhone();
break;
case 'Vivo':
FactoryPhone = new VivoPhone();
break;
default:
FactoryPhone = new XiaomiPhone();
break;
}
return FactoryPhone;
}
}
var IpadFactory = {
madeIpad: function(brand) {
var FactoryIpad;
switch(brand) {
case 'Apple':
FactoryIpad = new AppleIpad();
break;
case 'Huawei':
FactoryIpad = new HuaweiIpad();
break;
default:
FactoryIpad = new XiaomiIpad();
break;
}
return FactoryIpad;
}
}
//手机
function VivoPhone() {
this.starting = function() {};
this.notice = function() {
console.log('我新买的Vivo手机');
}
};
function ApplePhone() {this.starting = function() {};};
function HuaweiPhone() {this.starting = function() {};};
function XiaomiPhone() {this.starting = function() {};};
//平板电脑
function AppleIpad() {
this.starting = function() {};
this.notice = function() {console.log('新买的苹果平板')};
};
function HuaweiIpad() {this.starting = function() {};};
function XiaomiIpad() {};
var DayDayPhone = new PhoneOrIpadShop();
var havePhone = DayDayPhone.sellPhoneOrIpad("Ipad",'Apple');
havePhone.notice(); //新买的苹果平板
店长愁的一夜白了头,这是一夜回到解放前的节奏啊,本来管理的好好的,结果又像刚开始开店的时候了,要是开始卖自行车了又要大改了,开店的方法(构造函数),要添加种类的判断。我们可不可以通过工厂建造店铺(实例化),这样就可已卖单一商品了,原来的判断就不需要了。也就是把现在的工厂的对象改为构造函数。
那原来的那些活动怎么办,我们就一起拿过来,这就用到了继承。从店长家的店里继承过来,这时候店长家的店就好多了,不需要做哪些判断了,也不用用来作为开店的构造函数来用了,这部分的代码是这样的
继承的方法请看 《javaScript设计模式系列(五) 继承》。。。。 但是我还没有写,先记住一个关键字extend,用法是extend(子类,父类),这样就从继承来了父类原型的方法。
var PhoneFactory = function() {};
//继承父级的方法
extend(PhoneFactory, BaseShop);
PhoneFactory.prototype.madeProduct = function(brand) {
var Phone;
switch(brand) {
case 'Apple':
Phone = new ApplePhone();
break;
case 'Huawei':
Phone = new HuaweiPhone();
break;
case 'Vivo':
Phone = new VivoPhone();
break;
default:
Phone = new XiaomiPhone();
break;
}
return FactoryPhone;
}
var IpadFactory = function() {};
//继承父级的方法
extend(IpadFactory, BaseShop);
IpadFactory.prototype.madeProduct = function(brand) {
var Ipad;
switch(brand) {
case 'Apple':
Ipad = new AppleIpad();
break;
case 'Huawei':
Ipad = new HuaweiIpad();
break;
default:
Ipad = new XiaomiIpad();
break;
}
return Ipad;
}
那原来的店已经不需要用来实例化新店了,以前造电子啊产品的方法已经不能用了,怎么告诉别人呢?如果要调用店里制造商品的方法就报一个错误,告诉别人这个方法不能用,应为现在开店是用工厂开了。
function BaseShop() {};
BaseShop.prototype.lottery = function() {
console.log('您已经使用了一次抽奖机会');
};
BaseShop.prototype.gift = function() {
console.log('你获得了一些赠品');
};
BaseShop.prototype.sellProduct = function(brand) {
this.lottery();
this.gift();
var Product = this.madeProduct(brand);
Product.starting();
return Product;
};
BaseShop.prototype.madeProduct = function() {
console.log('madeProduct方法不能被使用,因为BaseShop是一个抽象类,不能实例化,只能派生子类');
}
sellProduct 方法不能被使用,它又会被继承到工厂里面怎么办,其实我们已经解决了,在工厂中的代码我们重写了sellProduct方法,覆盖了父级的方法。工厂是挂载基础店下的感觉,又有了基础店的方法。全部的代码就像下面:
function BaseShop() {};
BaseShop.prototype.lottery = function() {
console.log('您已经使用了一次抽奖机会');
};
BaseShop.prototype.gift = function() {
console.log('你获得了一些赠品');
};
BaseShop.prototype.sellProduct = function(brand) {
this.lottery();
this.gift();
var Product = this.madeProduct(brand);
Product.starting();
return Product;
};
BaseShop.prototype.madeProduct = function() {
console.log('madeProduct方法不能被使用,因为BaseShop是一个抽象类,不能实例化,只能派生子类');
}
var PhoneFactory = function() {};
//继承父级的方法
extend(PhoneFactory, BaseShop);
PhoneFactory.prototype.madeProduct = function(brand) {
var Phone;
switch(brand) {
case 'Apple':
Phone = new ApplePhone();
break;
case 'Huawei':
Phone = new HuaweiPhone();
break;
case 'Vivo':
Phone = new VivoPhone();
break;
default:
Phone = new XiaomiPhone();
break;
}
Interface.ensureImplements(Phone,PhoneInterface);
return Phone;
}
var IpadFactory = function() {};
//继承父级的方法
extend(IpadFactory, BaseShop);
IpadFactory.prototype.madeProduct = function(brand) {
var Ipad;
switch(brand) {
case 'Apple':
Ipad = new AppleIpad();
break;
case 'Huawei':
Ipad = new HuaweiIpad();
break;
default:
Ipad = new XiaomiIpad();
break;
}
Interface.ensureImplements(Ipad,IpadInterface);
return Ipad;
}
//手机
var PhoneInterface = new Interface('PhoneInterface',['starting','notice']);
function VivoPhone() {
this.starting = function() {};
this.notice = function() {
console.log('我新买的Vivo手机');
}
};
function ApplePhone() {
this.starting = function() {};
};
function HuaweiPhone() {
this.starting = function() {};
};
function XiaomiPhone() {
this.starting = function() {};
};
//平板电脑
var IpadInterface = new Interface('IpadInterface',['starting','notice']);
function AppleIpad() {
this.starting = function() {};
this.notice = function() {
console.log('新买的苹果平板')
};
};
function HuaweiIpad() {
this.starting = function() {};
};
function XiaomiIpad() {
this.starting = function() {};
};
var DayDayPhone = new IpadFactory();
var havePhone = DayDayPhone.sellProduct('Apple');
havePhone.notice(); //新买的苹果平板
总结一下,工厂模式可一实现松耦合,把公用的代码集中在一个地方,个体的代码写在子类中,这样如果需要较多的子类去组成一个较大的对象是很好管理的。