工厂模式

January 19, 2018 by Sylvenas

Simple Factory Pattern Intro

简单工厂模式的定义为定义一个工厂类,它可以根据参数的不同返回不同类的实例;简单工厂模式不属于GOF 23个经典设计模式之一,它的设计思想很简单,其基本流程如下:

  • 将需要创建的各种不同类型的对象的相关代码封装到不同的类中,这些类称为具体产品类。
  • 提供一个工厂方法用来创建产品,该方法可以根据所传入的参数不同创建不同的具体产品对象。
  • 客户端调用工厂方法并传入相应的参数。

Simple Factory Pattern Example

  • 封装产品生产
function LineChart() {
	this.type = '折线图';
}

function PieChart() {
	this.type = '饼状图';
}
  • 创建工厂方法
function Chart(type) {
	let chart;
	switch (type) {
		case 'line':
			chart = new LineChart();
			break;
		case 'pie':
			chart = new PieChart();
			break;
		default:
			break;
	}
	return chart;
}
  • 传入不同的参数生产产品
let chart = new Chart('line');

简单工厂模式优缺点

优点

  • 工厂方法必须包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端免除了直接创建产品对象的职责,而仅仅"消费"产品,实现了对象创建和使用的分离。
  • 使用者无须知道所创建的具体产品类的名称,只需要知道具体产品类所对应的参数即可,可以在一定程度上减少使用者的记忆量。

缺点

  • 工厂类集中了所有产品类的创建逻辑,一旦工厂类出现的异常,整个系统都要受到影响。
  • 系统扩展困难,一旦添加新产品就不得不修改工厂类逻辑,当产品类型较多的时候,可能会造成工厂逻辑过于复杂。

简单工厂模式适用场景

  • 工厂类负责创建的对象比较少,由于创建的对象比较少,则不会导致工厂类的逻辑过于复杂。
  • 客户端只知道传入工厂的参数,对于如何创建对象并不关心。

Factory Pattern Intro

工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类,该模式使类色实例化延迟到子类,而子类可以重写接口方法以便创建的时候制定自己的对象类型。换句更加通俗易懂的话来说就是:事先定义好每条流水线,每条流水线生产的东西是不一样的,然后工厂统一管理流水线,工厂通过订单类型来决定生产何种产品。

Factory Pattern Example

我们通过一个创建dom节点的例子,来看一下什么是工厂模式,以及工厂模式的工作流程:

创建图表库的例子

  • 预定义工厂流水线
const productFactory = {
	line: function () {
		this.type = '折线图';
	},
	pie: function () {
		this.type = '饼状图';
	}
};
  • 工厂方法统一管理流水线
function Chart(type) {
	return new productFactory[type]()
}
  • 封装生产产品实例
function Factory() {
	const productFactory = {
		line: function () {
			this.type = '折线图';
		},
		pie: function () {
			this.type = '饼状图';
		}
	};

	return function Chart(type) {
		return new productFactory[type]()
	}
}
const factory = Factory();
let chart = factory('pie');

创建DOM节点例子

  • 预定义工厂流水线
function createInput(type) {
	let el = document.createElement('input');
	el.type = type;
	return el;
};
const controls = {
	text: function (options) {
		let el = createInput(options.type);

		if (typeof options.value != 'undefined') {
			el.value = options.value;
		}
		return el;
	},
	checkbox: function (options) {
		let el = createInput(options.type);

		if (typeof options.checked != 'undefined') {
			el.checked = options.checked;
		}
		return el;
	}
};
  • 工厂统一管理流水线
function create(options) {
	let type = options.type ? options.type.toLowerCase() : undefined;

	if (!type || !controls[type]) {
		throw {
			message: type + ' is not supported.'
		}
	}

	return controls[type](options);
}
  • 根据订单生产指定产品
let text = create({ type: 'text', value: 'hello world' });

工厂模式优缺点

优点

  • 工厂方法在创建客户需要的产品的同时,隐藏了哪个具体产品类将要被实例化,用户只需知道所需产品对应的工厂,无须关心具体产品类的名称。
  • 在系统需要加入新的产品类的时候,完全无须修改工厂方法,只需要添加一个具体的产品类就可以了,增强了系统的可扩展性,符合"开闭原则"。

缺点

  • 在添加新的产品时,需要增加产品类的个数,在一定程度上增加了系统的复杂性。
  • 考虑了扩展性则必然增加了代码复杂性,不宜与理解和测试。

工厂模式适用场景

  • 对象的创建十分复杂。
  • 需要依赖不同环境创建不同实例。
  • 处理大量具有类似属性的小对象。