JS设计模式之“名片设计师” - 工厂方法模式

news2024/9/23 19:24:14

image.png

image.png

前言

上篇文章我们了解到什么是简单工厂模式,请参考上篇文章:JS设计模式之 “神奇的魔术师” - 简单工厂模式,不过这是工厂中最简单的一种,本篇文章我们将同大家一起认识一种更复杂的工厂模式,它将给我们提供复杂的对象创建场景,以模块化的思想实现我们复杂的需求。就像给我们设计不同的名片一样,我们暂且亲切的称呼它为“名片设计师”。

一. 什么是工厂方法模式

概念

工厂方法模式Factory Method Pattern)是一种创建型设计模式,在软件开发中被广泛应用。它提供了一种将对象的创建过程封装起来的方式,使得代码可扩展性更好、更灵活。

工厂方法模式的主要思想是定义一个用于创建对象的接口,但将具体的对象创建延迟到子类中去实现。这样,客户端程序使用工厂方法来创建对象,而不需要知道具体的实现细节,从而实现了解耦

fileOf7174.png

工厂方法模式类图

使用步骤

JavaScript 中,可以使用工厂方法模式实现对象的创建和管理,具体的实现方式如下:

首先,定义一个基础工厂类,作为对象创建的接口,其中包含一个用于创建对象的方法(通常称为工厂方法)。

class Factory {
  createObject() {
    // 子类需要实现该方法来创建具体对象
  }
}

然后,根据具体的需求,创建子类继承基础工厂类,并实现工厂方法来创建具体的对象。

class ConcreteFactory extends Factory {
  createObject() {
    return new ConcreteObject();
  }
}

最后,通过客户端代码来使用工厂方法创建对象。

const factory = new ConcreteFactory();
const object = factory.createObject();

使用工厂方法模式的好处是,当需要新增一种对象时,只需要创建一个新的子类并实现工厂方法即可,而不需要修改客户端代码。这样,能够降低代码的耦合度,提高代码的可维护性可扩展性

工厂方法模式是一种简单而有效的对象创建方式,适用于需要创建多个具有相同行为的对象的场景,能够提供一种灵活的对象创建和管理机制。

二. 安全模式创建的工厂类

介绍

安全模式创建的工厂类Safe Factory Pattern)是一种在JavaScript中实现工厂方法模式的方式,它可以确保只能通过工厂类的方法来创建对象,而不能直接实例化工厂类。

通过使用安全模式创建工厂类,可以确保工厂类的使用符合预期,同时也增强了代码的安全性和可靠性。以下是一个简单示例:

function Factory() {
  if (!(this instanceof Factory)) {
    return new Factory();
  }
  
  this.createObject = function() {
    // 创建对象的逻辑
  };
}

在上述示例中,我们使用了构造函数Factory)来实现工厂类,并通过判断this对象是否是工厂类的实例来确保只能通过构造函数来创建工厂类的实例。这样,在使用时如果忘记使用new关键字来实例化工厂类,则会自动进行实例化,避免了直接实例化工厂类导致的问题。

通过使用安全模式创建的工厂类,可以实现更严格的对象创建和管理机制,同时保证了代码的安全性和一致性。在实际应用中,可以根据需求对工厂类进行扩展和定制,以满足具体的业务需求。

优点

由此可见,安全模式创建的工厂类具有以下优点

1. 隐藏实例化细节: 安全模式的工厂类只能通过工厂方法来创建对象,而不允许直接实例化或继承该工厂类。这样可以隐藏具体对象的实例化细节,使得客户端无法直接访问和创建对象,只能通过工厂方法来获取实例。

2. 防止子类破坏对象的创建逻辑: 由于安全模式的工厂类不能被继承,子类无法改变工厂方法中的创建逻辑。这确保了对象的创建过程不会被子类随意修改,防止了在创建过程中可能出现的错误或安全隐患。

3. 提供一致的接口: 通过工厂方法来统一创建对象,工厂类可以根据不同的参数或条件返回不同类型的对象,但对外提供的接口是一致的。这样可以简化客户端的使用,客户端不需要知道具体的创建过程,只需要调用工厂方法并传入相应的即可获得所需对象。

案例场景:日志工厂

下面以一个Logger工厂类的示例来说明安全模式创建工厂类的优点:

public abstract class Logger {
    public abstract void log(String message);
}

public class FileLogger extends Logger {
    public void log(String message) {
        // 将日志信息写入文件
    }
}

public class DatabaseLogger extends Logger {
    public void log(String message) {
        // 将日志信息写入数据库
    }
}

public class LoggerFactory {
    private LoggerFactory() {}
    
    public static Logger createLogger type) {
        if (type.equals("file")) {
            return new FileLogger();
        } else if (type.equals("database")) {
            return new DatabaseLogger();
        } else {
            throw new IllegalArgumentException("Invalid logger type.");
        }
    }
}

在上述示例中,Logger是一个抽象类,具体的日志记录逻辑由FileLoggerDatabaseLogger来实现。LoggerFactory是一个安全模式创建的工厂类,通过工厂方法createLogger来创建Logger的实例。客户端只需调用LoggerFactorycreateLogger方法,并传入相应的参数(如filedatabase)即可获取对应的Logger实例。客户端无法直接实例化Logger类或LoggerFactory类,以保对象的创建逻辑被固定并且隐藏了具体实例化细节。这样的设计使得客户端使用起来更加简单方便,并且保护了对象创建过程的安全性和稳定性。

三. 简单工厂模式与工厂方法模式之间的对比

fileOf7174.png

披萨工厂

案例场景:披萨店点餐

当你在一个披萨店点餐时,你可以通过简单工厂模式或工厂方法模式来创建不同类型的披萨。这里有两个例子来说明它们之间的区别:

1. 简单工厂模式示例:

考虑一个披萨店,它提供不同类型的披萨,如奶酪披萨(Cheese Pizza)、蔬菜披萨(Vegetable Pizza)和海鲜披萨(Seafood Pizza)等。使用简单工厂模式,我们可以创建一个披萨工厂类来处理披萨的实例化逻辑:

public class PizzaFactory {
    public static Pizza createPizza(String type) {
        if (type.equals("cheese")) {
            return new CheesePizza();
        } else if (type.equals("vegetable")) {
            return new VegetablePizza();
        } else if (type.equals("seafood")) {
            return new SeafoodPizza();
        } else {
            throw new IllegalArgumentException("Invalid pizza type.");
        }
    }
}

public abstract class Pizza {
    // 披萨的公共方法和属性
}

public class CheesePizza extends Pizza {
    // 奶酪披萨特有的方法和属性
}

// 其他类型的披萨类类似,如VegetablePizza和SeafoodPizza

使用简单工厂模式,我们只需要通过披萨工厂类(PizzaFactory)来创建不同类型的披萨对象,而不需要直接实例化特定类型的披萨。

2. 工厂方法模式示例:

假设我们的披萨店进一步发展,对于不同类型的披萨,现在要创建不同的披萨店来处理它们的制作。这里为每个披萨类型创建一个具体的披萨店类,用工厂方法模式实现:

public abstract class PizzaStore {
    public abstract Pizza createPizza();

    public void orderPizza() {
        Pizza pizza = createPizza();
        // 其他制作披萨的逻辑
    }
}

public class CheesePizzaStore extends PizzaStore {
    public Pizza createPizza() {
        return new CheesePizza();
    }
}

// 其他类型的披萨店类类似,如VegetablePizzaStore和SeafoodPizzaStore

在工厂方法模式中,我们定义了一个抽象的PizzaStore类,并在每个具体的店类(如CheesePizzaStore)中实现了创建具体披萨对象的方法。每个具体的店类负责创建特定的披萨类型,使得披萨的创建逻辑分散到不同的类中。

通过上述两个示例可以看出,简单工厂模式通过一个工厂类集中处理对象的创建逻辑,而工厂方法模式将对象的创建推迟到具体的子类中实现,从而使得不同的产品创建逻辑能够被更加灵活地扩展和修改。

由此可见,整体区别如下:

工厂方法模式Factory Method Pattern)和简单工厂模式Simple Factory Pattern)是两种常见的工厂模式,它们之间有以下区别:

1. 设计理念:

  • 简单工厂模式的主要思想是通过一个工厂类来创建不同类型的对象,将对象的创建逻辑集中在一个地方。工厂类根据传入的参数或条件来决定创建哪种对象。

  • 工厂方法模式的主要思想是将对象的创建延迟到子类中实现。定义一个抽象的工厂类,该类中声明一个工厂方法,由子类来实现该工厂方法来创建具体的对象。

2. 参与角色:

  • 简单工厂模式通常只涉及一个工厂类(Simple Factory)和多个产品类(Product)。

  • 工厂方法模式涉及一个抽象工厂类(Abstract Factory)、多个具体工厂类(Concrete Factory)和对应的产品类(Product)。

3. 可扩展性:

  • 简单工厂模式的可扩展性相对较差,当需要新增一种产品时,需要修改工厂类的代码来增加对新产品的支持。

  • 工厂方法模式的可扩展性较好,通过添加一个新的具体工厂类和对应的产品类,即可实现对新产品的支持,不需要修改抽象工厂类或其他已有类。

4. 对象创建的灵活性:

  • 简单工厂模式在工厂类中集中了对象的创建逻辑,可能会导致工厂类变得较为庞大,一旦需要新增或修改某个产品的创建逻辑,就需要修改工厂类。

  • 工厂方法模式将对象的创建委托给具体的工厂类,每个工厂类只负责创建一个具体的产品,使得代码更加模块化和灵活,容易扩展和维护。

总结

简单工厂模式适用于简单的对象创建场景,可以通过一个工厂类来集中对象的创建逻辑;而工厂方法模式适用于复杂的对象创建场景,需要根据具体的产品类型来创建相应的对象,通过子类来实现对象的创建逻辑。选择使用哪种模式取决于具体的需求和设计的复杂性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2093862.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Kubernetes】声明式创建各种资源

k8s声明式创建 kubernetes陈述式创建与声明式创建yaml各个字段含义Pod yaml文件详解deployment.yaml文件详解server.yaml文件详解 k8s中port的区别1、声明式创建pod label包含app: zhangsan2、声明式创建deployment,包含3个nginx副本,label包含app: zhan…

【MyBatis】MyBatis的一级缓存和二级缓存简介

目录 1、一级缓存 1.1 我们在一个 sqlSession 中,对 User 表根据id进行两次查询,查看他们发出sql语句的情况。 1.2 同样是对user表进行两次查询,只不过两次查询之间进行了一次update操作。 1.3 一级缓存查询过程 1.4 Mybatis与Spring整…

Windows10上安装PostgreSQL 16

PostgreSQL是一个先进的、开源的、免费的、功能强大的关系型数据库,它使用并扩展了SQL语言,并结合了许多功能,可以安全地存储和扩展复杂的数据工作负载。PostgreSQL可在Windows、Linux、macOS等多个平台上运行,License使用Postgre…

hive学习(五)

一、hive的DML操作 1.load(向表中装载数据) hive> load data [local] inpath 路径 [overwrite] into table 表名 [partition (partcol1val1,…)];特殊说明 1)local:标识从本地加载数据到Hive表,若没有local的话从…

Linux系统下KubeSphere3.4.1离线安装包制作及部署过程

一、概述 KubeSphere 是 GitHub 上的一个开源项目,是成千上万名社区用户的聚集地。很多用户都在使用 KubeSphere 运行工作负载。对于在 Linux 上的安装,KubeSphere 既可以部署在云端,也可以部署在本地环境中,例如 AWS EC2、Azure…

JS设计模式之“幽灵工厂” - 抽象工厂模式

image.png 一. 了解带头模范 - 抽象类 JavaScript中并没有原生的抽象类的概念,但可以通过一些方式来模拟实现抽象类的效果。 抽象类是一种不能被直接实例化的类,只能作为其他类的基类使用。它定义了一组抽象方法,子类必须实现这些抽象方法。…

【函数模板】函数模板的类型推导

一、类型的自动推导 当函数模板的返回值被指定或与传入的参数的类型一致&#xff0c;那么可以直接调用函数模板&#xff0c;而不需要显式的指定参数。 //函数推导 template<typename T, typename R> T Add(T a, R b) {return a b; }void Test1() {//自动推导int x 1;…

【MySQL】索引使用规则——(覆盖索引,单列索引,联合索引,前缀索引,SQL提示,数据分布影响,查询失效情况)

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Lin…

【初出江湖】剖析软件架构发展之路

目录标题 架构发展历程单体架构&#xff08;Monolithic&#xff09;垂直拆分分布式服务微服务架构 SOAESB分布式微服务SOA&#xff0c;ESB&#xff0c;微服务的区别和关系分布式与微服务之间的区别于关系 架构发展历程 单体架构&#xff08;Monolithic&#xff09; 单体应用时…

Django 第十一课 -- ORM - 多表实例

目录 一. 前言 二. 创建模型 三. 插入数据 四. ORM - 添加数据 4.1. 一对多(外键 ForeignKey) 4.2. 多对多(ManyToManyField)&#xff1a;在第三张关系表中新增数据 4.3. 关联管理器(对象调用) 五. ORM 查询 5.1. 一对多 5.2. 一对一 5.3. 多对多 六. 基于双下划线…

eNSP-交换机的广播域和冲突域

一、广播域、冲突域 冲突域&#xff1a;一台电脑发送消息&#xff0c;其他电脑不能发送所影响的范围&#xff0c;就是冲突域。 广播域&#xff1a;一台电脑发送广播&#xff0c;所能广播到的范围。 二、举例 1.总线结构 广播域是整个总线的网络范围&#xff0c;冲突域也是整…

uniapp+vue3+setup返回上一页传参

huilderx 版本 list function getId(data) {// console.log(接收到的参数, data)if (data) {buildObj.value JSON.parse(data);} }onShow((options) > {getBuild() })// 暴露方法 defineExpose({getId })detail import { ref, onMounted, onUnmounted } from vue import…

ElasticSearch和Kibana的安全设置以及https设置

&#x1f468;‍&#x1f4bb;本文专栏&#xff1a;ElasticSearch和Kibana的安全设置以及https设置 &#x1f468;‍&#x1f4bb;本文简述&#xff1a;跟着猿灰灰一起学Java&#xff01; &#x1f468;‍&#x1f4bb;上一篇文章&#xff1a; &#x1f468;‍&#x1f4bb;有任…

3D打印透气钢与传统透气钢的差异

透气钢作为一种集金属强度与透气性能于一体的特殊材料&#xff0c;在注塑模具领域扮演着关键角色&#xff0c;通过有效排除模具内困气&#xff0c;显著提升制品成型质量与生产效率。当前&#xff0c;市场上主流的透气钢产品多源自日本、美国&#xff0c;其高昂成本与技术壁垒限…

【国铁采购平台-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

vue项目安装pnpm和无法加载pnpm,已解决

vue3安装pnpm命令&#xff1a; 1.提升依赖安装速度&#xff1a;npm config set registry https://registry.npmjs.org 2.安装pnpm:npm install -g pnpm 3.安装pnpm依赖&#xff1a;pnpm install 4…windows电脑&#xff0c;无法安装pnpm&#xff0c;pnpm install命令&#xff0…

C++基础知识七

1.对象拷贝时编译器优化 现代编译器为了尽快提高程序的效率&#xff0c;不影响正确性的情况下会尽可能减少一些传参和传参过程中可以省略的拷贝 例子&#xff1a; 先调用f&#xff08;&#xff09;函数&#xff0c;则应该先触发构造函数初始化a&#xff0c;return a时先拷贝a…

机器学习之监督学习(一)线性回归、多项式回归、算法优化[巨详细笔记]

机器学习之监督学习&#xff08;一&#xff09;线性回归、多项式回归、算法优化 1.监督学习定义2.监督学习分类2.1回归 regression2.2 分类 classification 3.线性回归 linear regression3.1 单特征线性回归模块一&#xff1a;梯度下降 3.2 多特征线性回归模块二&#xff1a;正…

CohereForAI更新企业级开源模型 c4ai-command-r-08-2024和c4ai-command-r-plus-08-2024

C4AI Command R 08-2024 是一个 350 亿参数高性能生成模型的研究版本。 Command R 08-2024 是一个大型语言模型&#xff0c;采用开放式权重&#xff0c;针对推理、总结和问题解答等各种用例进行了优化。 Command R 08-2024 具备多语言生成功能&#xff0c;曾在 23 种语言上进行…

nginx平滑升级与回滚

华子目录 升级实验环境准备测试内容准备实验要求实验步骤1.解压包2.检测1.26版本的环境3.make编译4.备份之前的nginx启动脚本5.将1.26中的nginx启动脚本覆盖掉1.24中的6.kill -USR2 旧主进程pid7.kill -WINCH 旧主进程pid 实验测试 回滚1.kill -HUP 旧主进程pid2.kill -WINCH 新…