设计模式之工厂模式

什么是工厂模式?

工厂模式属于创建型设计模式,将对象的创建与使用分离。

  • new 操作单独封装
  • 遇到 new时,就要考虑是否该使用工厂模式了

上面的两个概念也是比较抽象哈,我们可以结合现实中的例子去思考,假如你去买汉堡

  • 直接点餐、取餐,不会自己亲手做
  • 商店要"封装"做汉堡的工作,做好后直接给消费者

实现一个工厂模式

javascript 复制代码
class Product {
    constructor(name) {
        this.name = name
    }
    init() {
        console.log('init')
    }
    fn1() {
        console.log('fn1')
    }
    fn2() {
        console.log('fn2')
    }
}

class Creator {
    create(name) {
        return new Product(name)
    }
}

// 测试
// 创建一个工厂
let creator = new Creator() 
let p = creator.create('p1')
p.init()
// init
p.fn1()
// fn1

上面的代码也是比较简单,但是,其反映的思想就是工厂模式.

使用场景

工厂模式的代码和思想也是比较容易理解的,那么他在前端开发中,有什么样的应用场景呢?

Jquery

$('div')new $('div')有什么区别呢?

如果你用过 JQ,你会发现,我们在使用 JQ 的时候,根本不会去写 new $('div')这样的代码,也就是需要使用者去自己手动去new一个实例,首先这样写是比价麻烦的,再者,JQ的链式操作将成为噩梦,最致命的是,一但构造函数的命名发生变化,那将是灾难性的。所以,在使用JQ的时候,实际上我们用的是一种工厂模式,把实例化的过程和使用的过程分开。也就是$('div')的形式。比如下面这样的代码。

javascript 复制代码
class jQuery {
    constructor (seletor) {
        const slice = Array.prototype.slice
        const dom = slice.call(document.querySelectorAll(seletor)) // 过去dom节点,并返回一个数组(可能为多个dom节点)
        const len = dom ? dom.length : 0
        for(let i = 0; i < len; i++) {
            this[i] = dom[i] // 将选中的dom映射到this上
        }
        this.length = len
        this.seletor = seletor || ''

    }
    append(node) {

    }
    addClass(name) {

    }
    html(data) {

    }
    // 此处省略N个API
}

window.$ = function (selector) { // 这就相当于一个工厂
    return new jQuery(selector)
}

var p = $('p')
console.log(p)
console.log(p.addClass)
React.createElement

如果你使用过 React,我们知道 React 最著名的 JS X语法, 关于 JSX 语法,实际上他是一种语法糖,也就是 React.createElement 的语法糖,我们写的 JSX 语法,最终都会变成 React.createElement 的形式,我们通过传入各种标签名,最终生成 VNode 实例,也就是虚拟 DOM 节点,但是我们在开发的时候并不需要我们去写 new Vnode()这样的代码,这就是一种工厂模式。大家可以到Babel 的官网去自己手动试一下

而 React.createElement 的底层就是 new VNode() 这样的操作。大家不用太纠结这里的 react 的细节,我们主要是理解工厂模式,可以知道里面的思想即可。

Vue异步组件

使用过 Vue 的 Vue.component 这个方法一定不陌生,其中有一种异步组件的形式,代码大概就像下面这样

javascript 复制代码
Vue.component('async-component', (resolve, reject) => {
    setTimeout(() => {
         resolve({
            template: '<div>I am Async!</div>'
        })
    }, 1000)
})

上面最终返回了一个异步创建的组件,其也是一种工厂模式。

通过一个工厂类来创建其他类的实例
javascript 复制代码
class ProductA {
	constructor(name) {
		this.name = name;
	}
	operation() {
		console.log(`Product A (${this.name}) is working.`);
	}
}
class ProductB {
	constructor(name) {
		this.name = name;
	}
	operation() {
		console.log(`Product B (${this.name}) is working.`);
	}
}
class Factory {
	createProduct(type, name) {
		switch (type) {
			case 'A':
				return new ProductA(name);
			case 'B':
				return new ProductB(name);
			default:
				throw new Error('Invalid product type.');
		}
	}
}
const factory = new Factory();
const productA1 = factory.createProduct('A', 'productA1');
const productA2 = factory.createProduct('A', 'productA2');
const productB1 = factory.createProduct('B', 'productB1');
const productB2 = factory.createProduct('B', 'productB2');
productA1.operation(); 
// Product A (productA1) is working.
productA2.operation(); 
// Product A (productA2) is working.
productB1.operation(); 
// Product B (productB1) is working.
productB2.operation(); 
// Product B (productB2) is working.

上述代码中,我们创建了两个产品类 `ProductA` 和 `ProductB`,以及一个工厂类 `Factory`。工厂类提供了一个创建产品实例的方法 `createProduct`,该方法根据传入的参数来决定创建哪种产品实例。在主程序中,我们通过工厂类创建了四个不同的产品实例,并分别执行它们的操作方法。

相关推荐
刷帅耍帅35 分钟前
设计模式-享元模式
设计模式·享元模式
刷帅耍帅38 分钟前
设计模式-模版方法模式
设计模式
刷帅耍帅2 小时前
设计模式-桥接模式
设计模式·桥接模式
MinBadGuy3 小时前
【GeekBand】C++设计模式笔记5_Observer_观察者模式
c++·设计模式
刷帅耍帅4 小时前
设计模式-生成器模式/建造者模式Builder
设计模式·建造者模式
蜡笔小新..1 天前
【设计模式】软件设计原则——开闭原则&里氏替换&单一职责
java·设计模式·开闭原则·单一职责原则
性感博主在线瞎搞1 天前
【面向对象】设计模式概念和分类
设计模式·面向对象·中级软件设计师·设计方法
lucifer3111 天前
JavaScript 中的组合模式(十)
javascript·设计模式
lucifer3111 天前
JavaScript 中的装饰器模式(十一)
javascript·设计模式
蜡笔小新..1 天前
【设计模式】软件设计原则——依赖倒置&合成复用
设计模式·依赖倒置原则·合成复用原则