工厂模式
- 如果你不想让某个子系统与较大的那个对象之间形成强耦合,而是想运行时从许多子系统中进行挑选的话,那么工厂模式是一个理想的选择
- 将 new 操作简单封装,遇到 new 的时候就应该考虑是否用工厂模式;
- 需要依赖具体环境创建不同实例,这些实例都有相同的行为,这时候我们可以使用工厂模式,简化实现的过程,同时也可以减少每种对象所需的代码量,有利于消除对象间的耦合,提供更大的灵活性
根据不同的输入返回不同类的实例
将对象的创建和实现分离
例子:document.createElement 创建 DOM 元素
例子:利用工厂模式,提供 axios.create 静态方法
import {AxiosStatic,AxiosInstance, AxiosRequestConfig} from './types'
import Axios from './core/Axios'
import {extend} from './helpers/util'
import defaults from './default'
import mergeConfig from './core/mergeConfig'
function createInstance(config:AxiosRequestConfig):AxiosStatic{
const context = new Axios(config)
// 把Axios类隐藏,直接返回其main方法
// 可以通过 实例({参数}) 直接使用
const instance = Axios.prototype.request.bind(context)
extend(instance, context)
// 这里不标注instance而是static,因为类升级了,增加静态属性
return instance as AxiosStatic
}
const axios = createInstance(defaults)
// 增加静态create方法
axios.create = function create(config: AxiosRequestConfig | undefined){
return createInstance(mergeConfig(defaults,config))
}
export default axios
工厂负责创建产品,产品封装对象的具体实现
/* 产品类1 */
class Product1 {
constructor() {
this.type = "Product1";
}
operate() {
console.log(this.type);
}
}
/* 产品类2 */
class Product2 {
constructor() {
this.type = "Product2";
}
operate() {
console.log(this.type);
}
}
/* 工厂类 */
class Factory {
static getInstance(type) {
switch (type) {
case "Product1":
return new Product1();
case "Product2":
return new Product2();
default:
throw new Error("当前没有这个产品");
}
}
}
const prod1 = Factory.getInstance("Product1");
prod1.operate(); // 输出: Product1
const prod2 = Factory.getInstance("Product3"); // 输出: Error 当前没有这个产品
为什么使用工厂方法呢? 因为 new SomeClass 来构建对象本质上属于硬编码写死了类型。
为了将 object 的构建和使用分开,才引入了工厂函数作为中间抽象。
上面的例子中,使用工厂方法之后,还可以将 CarFactory.create 的参数写在配置文件,或者通过命令行传递。这样如果需要改变车辆品牌,只需要修改配置或者参数即可,不用修改编译代码。
仔细想一下,工厂方法其实和下面的代码没有本质区别。
之前 MAX 是硬编码的某个值,比如 100; 之后引入了函数 getMax,至于 getMax 返回 的值是怎么来的我们不关心,只要是 int 类型即可。 getMax 的角色和工厂方法是一样的。
// 简单工厂模式(静态工厂模式),用一个工厂对象创建同一类对象的实例
function Factory(career){
function User(carrer,work){
this.career = carrer
this.work = work
}
let work
swich(carrer){
case '清洁工':
work = ['