首页 > 其他分享 >前端必须掌握的设计模式——工厂模式

前端必须掌握的设计模式——工厂模式

时间:2024-12-11 22:31:33浏览次数:5  
标签:return 前端 工厂 class produce Ak47 设计模式 M4a1

目录

定义

简单工厂

标准工厂

抽象工厂

总结


定义

        工厂模式(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

相关文章

  • 转载:【AI系统】LLVM 前端和优化层
    在上一篇文章讲到了LLVM的IR贯穿了LLVM编译器的全生命周期,里面的每一个箭头都是一个IR的过程,这个就是整体LLVM最重要的核心概念。有了LVMIR之后这并不意味着LLVM或者编译器的整个Pipeline都是使用一个单一的IR,而是在编译的不同阶段会采用不同的数据结构,但总体......
  • 前端开发必备-带你了解CSS-IN-JS解决方案的优缺点
    前端开发必备-带你了解CSS-IN-JS解决方案的优缺点https://www.bilibili.com/video/BV1Ss4y1k7hBP101.专题内容介绍3.Emotion库P202.为什么会有CSS-IN_JS这种解决方案CSS-IN-JS是WEB项目中将CSS代码捆绑在JavaScript代码中的解决方案.这种方案旨在解决CSS的局限......
  • Web前端必学框架Bootstrap5
    https://www.bilibili.com/video/BV1Ez4y1q7oA/?spm_id_from=333.337.search-card.all.clickWeb前端必学框架Bootstrap5完整版从零入门到精通到实战(HTML/CSS/Bootstrap5/Vue/JS/零基础入门)S0051v3学过xv4没学旧中不学v5学P101_Bootstrap简介Bootstrap是一个用于快速开......
  • 329.大学生HTML期末大作业 —【纪念鲁迅文化主题网页】 Web前端网页制作 html+css
    目录一、更多推荐二、网页简介三、网页文件四、网页效果五、代码展示1.html2.CSS六、总结1.简洁实用2.使用方便3.整体性好4.形象突出5.交互式强一、更多推荐欢迎来到我的CSDN主页!您的支持是我创作的动力!Web前端网页制作、网页完整代码、大学生期末大作业案例......
  • Web前端-3小时教你打造一个聊天室(websocket)
    Web前端-3小时教你打造一个聊天室(websocket)01-websocket概念02-H5中新增的websocketAPI03-nodejs开发自己的websoket服务04-使用websocket开发一个基本的聊天室05-使用websocket实现简单的聊天室06-socketio的基本用法07-socketio的基本用法08-使用socketio开发聊天室-登......
  • Joker 前端框架组件的生命周期
    Joker前端框架组件的生命周期在Joker框架中,组件的生命周期是一个重要的概念,它涵盖了从组件实例化到销毁的整个过程。一、生命周期概述当组件类被实例化并开始渲染其视图及其子视图时,组件的生命周期便正式开始。在这个过程中,Joker会持续进行变更检测,监控数据绑定属性的变化,......
  • Joker 前端框架组件的生命周期:深度解析与实践应用
    在Joker前端框架的开发体系中,组件的生命周期犹如一颗精准的导航星,指引着开发者构建高效、稳定且富有交互性的应用程序。它完整地涵盖了从组件实例诞生的那一刻起,直至其完成使命被销毁的全过程,每一个阶段都蕴含着独特的意义与功能。一、生命周期:全景扫描当一个组件类被实例化,犹......
  • 转载:【AI系统】LLVM 前端和优化层
    在上一篇文章讲到了LLVM的IR贯穿了LLVM编译器的全生命周期,里面的每一个箭头都是一个IR的过程,这个就是整体LLVM最重要的核心概念。有了LVMIR之后这并不意味着LLVM或者编译器的整个Pipeline都是使用一个单一的IR,而是在编译的不同阶段会采用不同的数据结构,但总体......
  • Kotlin设计模式之解释器模式
    解释器模式(Interpreter Pattern)用于定义一个语言的文法表示,并建立一个解释器来解释该语言中的句子。以下是Kotlin中实现解释器模式的几种方法:一.基本解释器模式在这种模式中,定义一个表达式接口,并实现具体的表达式类。//Expression.ktinterfaceExpression{funint......
  • Kotlin设计模式之中介者模式
    中介者模式(MediatorPattern)用于定义一个对象,该对象封装了一组对象之间的交互方式。中介者使各对象不需要显式地相互引用,从而使其耦合松散,并可以独立地改变它们之间的交互。以下是Kotlin中实现中介者模式的方法:基本中介者模式在这种模式中,定义一个中介者接口和具体的中介者类......