JavaScript设计模式-工厂模式

简单工厂

简单工厂通常是一个对象,对象中包含一些可以复用的方法,如果需要改动,只需要改动工厂中的方法就可以实现全部更新。

let BicycleFactory = {
	createBicycle(model){
	let bicycle = null;
		switch(model){
			case 'speeder':
				bicycle = new Speeder();
				break;
			case 'Lowest':
				bicycle = new Lowest();
				break;
		}
		return bicycle;
	}
}

工厂模式

工厂是一个将其成员对象的实例化推迟到子类中进行的类。
真正的工厂模式与简单的工厂模式的区别在于,工厂模式不使用一个对象,而是使用一个子类实现创建新实例的方法。

let BicycleShop = function () {
	
}
BicycleShop.prototype.sellBicycle = function () {
	let bicycle = this.creatwBicycle(model);
	bicycle.wash();
}

let AssmBicycleShop = function (){
	
}
AssmBicycleShop.prototype.createBicycle = function (model) {
	let bicycle = null;
	switch(model){
		case 'speeder':
			bicycle = new Speeder();
			break;
	}
	return bicycle;
}

父类中的公共方法需要使用一个对象进行操作,这个对象的创建应该由子类创建。

function Animal() {

}
Animal.prototype.prototype.talk = function () {
	let dog = this.createDog();
	dog.talk();
}

function Dog() {
	
}
Dog.prototype.createDog = function (model) {
	let dog = null;
	switch(model){
		case 'gray':
			dog = new Gray();
			break;
	}
	return dog;
}
Dog.prototype.talk = function () {
	console.log("wang");
}

Dog类需要继承Animal类。
父类或构造器要实现公共的方法。

用工厂模式创建XHR对象

function XHRFactory() {
	
}
XHRFactory.prototype.createXhrObect = function () {
	let methods = [
		function () {return new XMLHttpRequest()},
		function () {return new ActiveXObject('Msxml2.XMLHttp')},
		function () {return new ActiveXObject('Miscrosoft.XMLHttp')}
	];
	for(let i = 0; i < methods.length; i++) {
		try{
			methods[i]();
		}catch{
			continue;
		}
		this.createXhtObject = methods[i];
		return methods[i]();
	}
}
XHRFactory.prototype.request = function (success, fail) {
	let xhr = this.createXhrObject();
	xhr.onreadystatechange = function () {
		if(xhr.stete === 4 && xhr.status === 200){
			success(xhr.reposneText);
			
		} else {
			fail(xhr.status);
		}
	}
}

第二次执行request时createXhtObject就变成了

createXhrObject = function () {
	return new XMLHttpRequest();
}

根据不同浏览器的实现发生变化。

抽象工厂模式

通过对类的工厂抽象使其业务用于对产品类簇的创建,而不负责创建某一类产品的实例。

// 抽象类,用于创建子类
function Person(name, age) {
  this.name = name;
  this.age = age;
  Person.prototype.getName = function () {
   throw new Error('抽象方法不能被调用');
  }
  Person.prototype.getAge = function () {
  throw new Error('抽象方法不能被调用');
  }
}
// 抽象工厂,创建的不是一个具体的实例,而是一个类簇,规定了该类对象的结构
function AbstractFactory(subType, superType) {
  if (typeof AbstractFactory[superType] === 'function') {
    function fn() {}
    fn.prototype = new AbstractFactory[superType]();
    subType.prototype = new fn();
  }
}

AbstractFactory.Person = Person;
// 基类,用于创建具体的对象实例
function Student(name, age){
	this.name = name;
	this.age = age;
}

Student.prototype.getName = function () {
return this.name;
}

Student.prototype.getAge = function(){
	return this.age;
}

AbstractFactory(Student, 'Person');
let liming = new Student();
liming.getName();
liming.getAge();

工厂模式的适用场合

动态实现

不同方式实现统一接口的对象,使用工厂方法简化选择的过程。这种选择可以是明确的,也可以是隐含的。

节省设置开销

如果对象需要复杂并且彼此相关的设置,那么工厂模式可以减少每种对象所需的代码量。

用许多小型对象组合成一个大对象

工厂方法可以用来创建封装了许多小对象的对象。

function Display(listDisplay, fieldsetDisplay, config){
	this.listDisplay = listDisplay;
	this.fieldsetDisplay = fieldsetDisplay;
	this.config = config;
}
function ListDisplay(list){
	this.list = list;
}
function FieldsetDisplay(fieldset) {
	this.fieldset = fieldset;
}

let config = {
	id:'root',
	updateInterval:60
}
let displayManager = {
	createDisplayer(){
		let listDisplay = new ListDisplay();
		let fieldsetDisplay = new FieldsetDisplay();
		return new Display(listDisplay, fieldsetDisplay, config);
	}
}

displayManager 先创建所需要的其他对象,然后将这些对象传递给 Display 生成一个包含这些对象的大对象。

优缺点

优点

  1. 消除对象间的耦合
  2. 在派生子类时提供了更大的灵活性
    可以先创建一个抽象的父类,在子类中创建工厂方法,这样可以把实例化推迟到专门化的子类中

缺点

  1. 容易被滥用
    工厂函数可以把具体的实现进行封装,容易把工厂模式当成万金油,用其取代构造函数。
    如果不需要在运行期间在多个类之间进行选择,就不要使用工厂模式。

  2. 隐藏具体的对象构造
    由于工厂函数把对象的实例化过程进行封装,有时需要查看代码才能知道实例化的是什么类。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端御书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值