文档章节

javaScript设计模式系列(四) 工厂模式

Say_-no
 Say_-no
发布于 2017/07/07 11:03
字数 2206
阅读 5
收藏 1

前言

工厂这个名词我们可以先分析一下,一般工厂的特点都是大批量的造东西,要是只做一个的话,倒是可以在家搭个小作坊,半年产值一个也是可以的。再有呢,工厂普遍是单一生产,哪怕是产品功能改了,那我就把流水线改一改,换几个机组,大的流程还是不变的。那如果要是,工厂今天造船,明天想造飞机,基本是没戏,造飞机和造船是完全不同的两套流程和设备,这么大的变动,不是一个工厂想改就改的。

正文:

现在正好有一个店家在卖手机,他们自己做手机自己销售,这店家就叫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(); //新买的苹果平板

总结一下,工厂模式可一实现松耦合,把公用的代码集中在一个地方,个体的代码写在子类中,这样如果需要较多的子类去组成一个较大的对象是很好管理的。

© 著作权归作者所有

Say_-no
粉丝 1
博文 6
码字总数 9308
作品 0
昆明
私信 提问
《JavaScript设计模式与开发实践》原则篇(2)—— 最少知识原则

最少知识原则(LKP)说的是一个软件实体应当尽可能少地与其他实体发生相互作用。这 里的软件实体是一个广义的概念,不仅包括对象,还包括系统、类、模块、函数、变量等。 单一职责原则指导我们...

嗨呀豆豆呢
2018/12/30
0
0
《JavaScript设计模式与开发实践》最全知识点汇总大全

系列文章: 《JavaScript设计模式与开发实践》基础篇(1)—— this、call 和 apply 《JavaScript设计模式与开发实践》基础篇(2)—— 闭包和高阶函数 《JavaScript设计模式与开发实践》模式...

嗨呀豆豆呢
01/04
0
0
《JavaScript设计模式与开发实践》模式篇(12)—— 装饰者模式

在传统的面向对象语言中,给对象添加功能常常使用继承的方式,但是继承的方式并不灵活, 还会带来许多问题:一方面会导致超类和子类之间存在强耦合性,当超类改变时,子类也会随之 改变;另一方...

嗨呀豆豆呢
2018/12/25
0
0
JavaScript设计模式系列三之单例模式(附案例源码)

文章初衷 设计模式其实旨在解决语言本身存在的缺陷 目前javaScript一些新的语法特性已经集成了一些设计模式的实现, 大家在写代码的时候,没必要为了用设计模式而去用设计模式, 那么我这边为什...

小钱钱阿圣
2017/09/22
0
0
JavaScript设计模式总结

之前看过《JavaScript设计模式与开发实践》这本书,对书中的设计模式和一些相关案例也有了一定的了解,同时把这些设计模式的应用对应在在一些其他的项目中,进行了一些整理,如下仅供参考: ...

jefferyE
03/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

rime设置为默认简体

转载 https://github.com/ModerRAS/ModerRAS.github.io/blob/master/_posts/2018-11-07-rime%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%BB%98%E8%AE%A4%E7%AE%80%E4%BD%93.md 写在开始 我的Arch Linux上......

zhenruyan
今天
5
0
简述TCP的流量控制与拥塞控制

1. TCP流量控制 流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。 原理是通过确认报文中窗口字段来控制发送方的发送速率,发送方的发送窗口大小不能超过接收方给出窗口大小。...

鏡花水月
今天
10
0
OSChina 周日乱弹 —— 别问,问就是没空

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @tom_tdhzz :#今日歌曲推荐# 分享容祖儿/彭羚的单曲《心淡》: 《心淡》- 容祖儿/彭羚 手机党少年们想听歌,请使劲儿戳(这里) @wqp0010 :周...

小小编辑
今天
1K
11
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
5
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部