目录
定义
工厂模式(Factory Pattern)属于 创建型 设计模式。指的是利用工厂这个媒介,提供统一的接口,从而获得对象。对于客户端而言,只需将创建对象的命令告诉工厂,具体的创建逻辑客户端是不知道的。
工厂模式可以分为两个角色:
- 工厂:只负责创建对象的逻辑,不用管其他的逻辑。
- 产品:调用工厂提供的接口,从而获取对象。
工厂模式根据不同的场景大致有三种,分别是“简单工厂”、“标准工厂”和“抽象工厂”,以下分别介绍这三种工厂模式变体。
简单工厂
简单工厂,就是最简单的一种工厂方法,利用一个静态方法,根据传递进来的参数进行判断,从而创建不同的对象。举个例子,我们希望生产一把“AK47”和一把“M4A1”。
我们需要定义一个工厂帮我们创建,我们只需要对工厂“下订单”即可。画出UML图如下,先定义一个枪支生产的接口IGun,再定义两个类“Ak47”和“M4a1”分别去实现IGun接口。最后定义一个工厂类GunFactory,在工厂类中定义一个静态方法createGun,通过客户端传递的参数type去映射,是new Ak47()呢还是new M4a1()。
客户端只需要通过GunFactory类调用静态方法,传递参数完成生产枪的指令,交给GunFactory工厂类去调度, 创建对象最终生产出想要的枪支,代码如下。
// 定义枪械的接口
interface IGun {
produce(): void; // 生产枪械
}
class Ak47 implements IGun {
produce() {
console.log('Ak47 completed!');
}
}
class M4a1 implements IGun {
produce() {
console.log('M4a1 completed!');
}
}
// 枪械工厂类
class GunFactory {
static createGun(type: string): IGun {
switch(type) {
case 'ak47':
return new Ak47();
case 'm4a1':
return new M4a1();
default:
throw new Error('type is not exist');
}
}
}
// 客户端 不需要引入具体的产品类 通过工厂类创建具体产品
const gun1 = GunFactory.createGun('ak47');
const gun2 = GunFactory.createGun('m4a1');
gun1.produce(); // Ak47 completed!
gun2.produce(); // M4a1 completed!
标准工厂
标准工厂的产生,源于简单工厂本身存在一些问题,算是对简单工厂模式的优化,一般也叫做具体工厂。我们细品代码其实可以看出,简单工厂的工厂类职责过多,强耦合;违背开闭原则,如果新增一个AWM类,则需要修改工厂类内部代码,容易对原有逻辑产生影响。
那么为了解决这个问题,针对工厂类进行解耦,将一个产品对应一个工厂,定义两个工厂“Ak47Factory”和“M4a1Factory”,分别生产“Ak47”和“M4a1”。再定义一个工厂方法,根据传入的对象执行不同产品的生产逻辑。
客户端通过创建具体的工厂对象,传给factory进行调度,使用创建出来的工厂对象调用对象内部的produce方法,从而生产出想要的枪支,代码如下。
// 定义枪械的接口
interface IGun {
produce(): void; // 生产枪械
}
class Ak47 implements IGun {
produce(): void {
console.log('Ak47 completed!');
}
}
class M4a1 implements IGun {
produce(): void {
console.log('M4a1 completed!');
}
}
// 定义工厂的接口
interface IFactory {
createGun(): IGun; // 修改返回类型为 IGun
}
class Ak47Factory implements IFactory {
createGun(): IGun {
return new Ak47();
}
}
class M4a1Factory implements IFactory {
createGun(): IGun {
return new M4a1();
}
}
const factory = (factory: IFactory) => {
const fac = factory.createGun();
fac.produce();
};
factory(new Ak47Factory()); // Ak47 completed!
factory(new M4a1Factory()); // M4a1 completed!
对比简单工厂,标准工厂模式如果新增一个AWM,仅仅是添加AWM产品和AWM工厂,并未对之前的产品和工厂产生耦合的逻辑,虽然代码变多了,但属于线性增添是可接受的范围,最重要的是符合开闭原则。
抽象工厂
有这么一种情况,客户想要创建一系列的产品。举个例子,Ak47、M4a1、Awm这三种类型的枪支都可以做涂装,简单分为炫彩、黄金和英雄,客户想要同时生产黄金Ak47、黄金M4a1、黄金Awm。
如果使用标准工厂模式,我们经过排列组合需要创建9个工厂,随着枪支类型和涂装不断增加,我们要新建和维护的工厂呈指数级增长。那么抽象工厂的作用就体现出来了,抽象工厂无需指定类,定义一个抽象工厂AbstractFactory,具体的炫彩、黄金、英雄工厂(这里仅写了炫彩工厂)都继承抽象工厂。
定义一个客户类Client,定义一个方法produceGuns用来执行生产逻辑,这里需要传入对应的具体工厂对象,用该工厂对象调用对应的create方法。
// 抽象产品类 Ak47 M4A1 Awm
abstract class Ak47 {
abstract produce(): string;
}
abstract class M4a1 {
abstract produce(): string;
}
abstract class Awm {
abstract produce(): string;
}
// 具体产品 - 炫彩Ak47
class ColorfulAk47 extends Ak47 {
produce(): string {
return 'colorful Ak47';
}
}
// 具体产品 - 炫彩M4a1
class ColorfulM4a1 extends M4a1 {
produce(): string {
return 'colorful M4a1';
}
}
// 具体产品 - 炫彩Awm
class ColorfulAwm extends M4a1 {
produce(): string {
return 'colorful Awm';
}
}
// 具体产品 - 黄金Ak47
class GoldAk47 extends Ak47 {
produce(): string {
return 'gold Ak47';
}
}
// 具体产品 - 黄金M4a1
class GoldM4a1 extends M4a1 {
produce(): string {
return 'gold M4a1';
}
}
// 具体产品 - 黄金Awm
class GoldAwm extends Awm {
produce(): string {
return 'gold Awm';
}
}
// 具体产品 - 英雄Ak47
class HeroAk47 extends Ak47 {
produce(): string {
return 'hero Ak47';
}
}
// 具体产品 - 英雄M4a1
class HeroM4a1 extends M4a1 {
produce(): string {
return 'hero M4a1';
}
}
// 具体产品 - 英雄Awm
class HeroAwm extends Awm {
produce(): string {
return 'hero Awm';
}
}
// 定义抽象工厂
abstract class AbstractFactory {
abstract createAk47(): Ak47;
abstract createM4a1(): M4a1;
abstract createAwm(): Awm;
}
// 生产炫彩涂装的工厂
class ColorfulFactory extends AbstractFactory{
createAk47(): Ak47 {
return new ColorfulAk47();
}
createM4a1(): M4a1 {
return new ColorfulM4a1();
}
createAwm(): Awm {
return new ColorfulAwm();
}
}
// 客户端类
class Client {
private factory: AbstractFactory;
constructor(fac: AbstractFactory) {
this.factory = fac;
}
public produceGuns(): string {
// 生产对应涂装的一套枪械
const ak47 = this.factory.createAk47();
const m4a1 = this.factory.createM4a1();
const awm = this.factory.createAwm();
return `${ak47.produce()}-${m4a1.produce()}-${awm.produce()}`;
}
}
// 客户要生产一套炫彩枪械
const fac = new ColorfulFactory();
const client = new Client(fac);
const info = client.produceGuns();
console.log(info); // colorful Ak47-colorful M4a1-colorful Awm
总结
总结一下工厂模式,首先是简单工厂是为了避免暴露创建对象具体的细节,但是存在工厂负担过重的问题,所以用标准工厂去解耦,形成一个产品一个工厂的局面;当有一组产品需要生产是引入了抽象工厂,解决群组和系列生产的问题。前端必须掌握的设计模式系列持续更新,如果对您有帮助希望多多点赞哦!
标签:return,前端,工厂,class,produce,Ak47,设计模式,M4a1 From: https://blog.csdn.net/mayuhao0000/article/details/144400456