【利用AI让知识体系化】5种创建型模式
文章目录
- 创建型模式
- 简介
- 工厂模式
- 抽象工厂模式
- 单例模式
- 建造者模式
- 原型模式
创建型模式
简介
创建型模式,顾名思义,是用来创建对象的模式。在软件开发中,对象的创建往往比一般的编程任务更为复杂,可能涉及到一些琐碎、复杂的过程,例如对象内部的依赖关系确定、对象的实例化方式等。创建型模式的主要功能是将对象的创建过程封装起来,从而隐藏其复杂性,并且可以为客户端提供一种灵活的创建对象的方式。
常见的创建型模式包括:
- 工厂模式(Factory Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 单例模式(Singleton Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype Pattern)
这些模式可以被分为两类:类创建型模式和对象创建型模式。类创建型模式通过一个类来创建对象实例,而对象创建型模式则通过一个对象来创建新的对象实例。同时,许多创建型模式都执行一些形式的延迟初始化,我们称之为“惰性初始化”,也是许多模式关注的问题之一。
总之,创建型模式主要解决了对象创建过程中的复杂性和灵活性问题,提高了代码的可复用性和可读性。在软件开发中,根据不同的场景和需求选择合适的创建型模式可以帮助开发者更好地完成对象的创建工作。
工厂模式
工厂模式是一种创建型设计模式,它定义了一个用于创建对象的接口,让子类来决定将哪一个类实例化。工厂模式使得创建对象变得更加灵活和可扩展,它将创建具体对象的责任转移给了子类,而不是在客户端代码中直接实例化对象。
工厂模式常用于以下场合:
- 对象创建需要复杂的逻辑
- 对象的创建涉及到大量的重复代码
- 使用工厂模式可以封装类的实例化过程
工厂模式的核心是一个抽象工厂(Factory)类
,该类定义了一个创建对象的抽象方法,子类可以通过实现该抽象方法来创建具体的对象。具体工厂类(Concrete Factory)
是工厂模式的重要组成部分,主要负责实现抽象工厂类中定义的抽象方法,以便生产出具体的产品。
有两种基本的工厂模式:简单工厂模式和工厂方法模式。简单工厂模式只是用来创建单一类型的对象,而工厂方法模式则可以用来创建一组相关的对象。同时还有一个抽象工厂模式,它用于创建多个产品系列以及产品之间的关联,属于更高层次的模式。
总之,工厂模式可以帮助客户端代码解耦,将对象的实例化过程封装在工厂类中,让程序更加灵活和可扩展。它是一种非常常见的设计模式,被广泛应用于软件开发的各个领域。
这是一个使用 JavaScript 实现的工厂模式的简单示例:
class Product {constructor(name) {this.name = name;}
}class ProductA extends Product {constructor() {super("ProductA");}
}class ProductB extends Product {constructor() {super("ProductB");}
}class Creator {factoryMethod() {}
}class CreatorA extends Creator {factoryMethod() {return new ProductA();}
}class CreatorB extends Creator {factoryMethod() {return new ProductB();}
}
抽象工厂模式
抽象工厂模式是一种创建型设计模式
,它提供了一种创建一系列相关或者相互依赖对象的接口,而无需指定实现类。简单来说,抽象工厂模式是一种工厂模式的扩展,可以创建一组相关的对象,而不仅仅是一个对象。
抽象工厂模式常用于以下场合:
- 当需要创建一系列相关或相互依赖的对象时
- 需要提供一个统一的接口,以便客户端通过抽象接口使用多个具体产品中的一种
- 由于业务需求的变化,需要支持新的产品系列
抽象工厂模式由抽象工厂、具体工厂、抽象产品和具体产品四个部分组成。
- 抽象工厂(Abstract Factory):定义了创建一系列相关或依赖对象的方法。
- 具体工厂(Concrete Factory):实现抽象工厂定义的方法,返回一组相关的产品。
- 抽象产品(Abstract Product):定义一类产品的接口。
- 具体产品(Concrete Product):实现抽象产品的接口,是抽象工厂创建的对象。
抽象工厂模式可以看做是一组工厂方法的组合,它提供了一种更高层次的抽象,能够将多个相关的对象创建放在同一个工厂中,这样可以更好地维护产品之间的兼容性。
总的来说,抽象工厂模式广泛应用于需要创建一组相关或依赖对象的场合,它使得客户端代码与具体产品的实现相分离,提高了程序模块化和可维护性
。
这是一个使用 JavaScript 实现的简单的抽象工厂模式的示例:
class AbstractProductA {constructor() {if (new.target === AbstractProductA) {throw new Error("Cannot instantiate abstract class");}}methodA() {}
}class AbstractProductB {constructor() {if (new.target === AbstractProductB) {throw new Error("Cannot instantiate abstract class");}}methodB() {}
}class ProductA1 extends AbstractProductA {methodA() {console.log("Product A1 - Method A");}
}class ProductA2 extends AbstractProductA {methodA() {console.log("Product A2 - Method A");}
}class ProductB1 extends AbstractProductB {methodB() {console.log("Product B1 - Method B");}
}class ProductB2 extends AbstractProductB {methodB() {console.log("Product B2 - Method B");}
}class AbstractFactory {createProductA() {}createProductB() {}
}class ConcreteFactory1 extends AbstractFactory {createProductA() {return new ProductA1();}createProductB() {return new ProductB1();}
}class ConcreteFactory2 extends AbstractFactory {createProductA() {return new ProductA2();}createProductB() {return new ProductB2();}
}
在这个示例中,我们定义了两个抽象产品类 AbstractProductA
和 AbstractProductB
,以及两个具体的产品类 ProductA1
、ProductA2
,以及 ProductB1
、ProductB2
。然后我们定义了一个抽象工厂类 AbstractFactory
,并在其中定义了两个抽象方法 createProductA()
、createProductB()
,分别用于创建 AbstractProductA
和 AbstractProductB
的实例。最后,我们又定义了两个具体的工厂类 ConcreteFactory1
和 ConcreteFactory2
,并分别实现了 AbstractFactory
中的抽象方法。在 ConcreteFactory1
中,实现了 createProductA()
返回 ProductA1
的实例,实现了 createProductB()
返回 ProductB1
的实例。在 ConcreteFactory2
中,实现了 createProductA()
返回 ProductA2
的实例,实现了 createProductB()
返回 ProductB2
的实例。
单例模式
单例模式是一种创建型设计模式,它保证一个类只有一个实例,并提供一个访问这个实例的全局点。单例模式在实际开发中经常用于控制资源的使用,例如全局缓存、配置对象、线程池、数据库连接池等。
单例模式保证了系统中一个类只有一个实例,从而避免了多个实例的产生,节省了系统资源,使得代码执行更加高效、可维护和可扩展。同时,单例模式的实现很简单,只需要提供一个静态方法,返回同一个实例即可。
常见的单例模式实现方式有两种:懒汉式单例模式和饿汉式单例模式。
1. 懒汉式单例模式
懒汉式单例模式是指在第一次获取实例时才进行实例化。优点是可以节省系统资源,缺点是会存在线程安全问题,需要加入同步锁来解决。
2. 饿汉式单例模式
饿汉式单例模式是指在程序启动时进行实例化,不管实例是否被使用。优点是不会出现线程安全问题,缺点是可能会浪费资源,因为实例在程序启动时就被创建,可能在之后并没有被使用到。
同时,单例模式的实现也包括线程安全的单例模式(使用双重检查锁等机制确保线程安全)、枚举类型的单例模式等。此外,单例模式也有一些缺点,例如扩展困难、测试困难等,开发者需要根据实际业务场景来灵活运用单例模式。
总之,单例模式是一种非常常用的设计模式,它可以保证系统中某个类只有一个实例,从而提升系统的性能和可维护性
。在实际开发中,需要根据具体业务场景来选择单例模式的实现方式,同时需要注意线程安全和可测试性等问题。
这是一个使用 JavaScript 实现的简单的单例模式的示例:
class Singleton {constructor() {if (!Singleton.instance) {Singleton.instance = this;}return Singleton.instance;}someMethod() {console.log("Some method of the Singleton");}
}
在这个示例中,我们定义了一个类 Singleton
,并在其构造函数中使用了一个静态变量 instance
。当我们创建这个类的实例时,我们先检查它是否已经存在,如果不存在则创建一个新实例并将其存储在静态变量 instance
中,然后返回这个实例。这样,我们就始终只有一个类的实例被创建,并且可以随时访问它的方法。在这里,我们定义了一个方法 someMethod()
作为单例对象的一个例子。
建造者模式
建造者模式是一种创建型设计模式,它将一个复杂对象的构建与它的表示分离,可以让同样的构建过程创建不同的表示。
建造者模式通常适用于以下情况:
- 创建复杂对象时,对象的内部构造非常复杂(多个组件、不同的构造顺序等)
- 通过不同的组装顺序可以创建出不同的对象表示
- 在对象构造过程中需要进行很多控制,例如参数校验、类型判断等
建造者模式的核心是一个建造者(Builder
)和一个指挥者(Director
)。建造者负责创建产品的各个部分,而指挥者负责调用建造者来创建产品,并且按照一定的组装顺序来完成产品的创建。建造者模式将一个复杂对象的创建过程进行了拆分,使得在某个步骤出现问题时,不需要整个重新开始构建,只需要针对问题的步骤进行调整即可。
建造者模式的实现通常包括以下几个角色:
- 抽象建造者(
Builder
):定义创建产品各个部分的抽象方法 - 具体建造者(
Concrete Builder
):实现抽象建造者定义的方法,并返回组装好的产品实例 - 产品(
Product
):定义由各个部分组成的复杂对象 - 指挥者(
Director
):负责调用具体建造者来创建产品,在指挥者中也可以定义具体的组装顺序。
在建造者模式中,客户端通常只需关心指挥者和具体建造者,不需要知道产品的具体实现细节。通过将对象的创建和表示分离,建造者模式可以更好地控制对象的创建过程,从而创建出更加灵活和适用的产品。
总的来说,建造者模式适用于创建那些结构复杂,内部组合关系较为复杂的对象。它的实现较为复杂,但是可以提高代码的可复用性和可维护性,同时也可以增加代码的可扩展性。
原型模式
原型模式是一种创建型设计模式,它使用原型实例指定要创建对象的类型,然后通过复制这个原型来创建新的对象
。在原型模式中,不需要知道任何对象的创建细节,只需知道需要创建的对象类型即可。
原型模式通过克隆复制一个已有对象来创建新的对象,可以大大减少创建对象的时间,并且可以避免由于手动创建对象而引入的错误。原型模式在实际开发中应用广泛,常用于创建那些具有相似属性的对象,例如创建相似的数据库连接对象或线程池中的线程对象等。
原型模式的核心是原型接口(Prototype
),该接口定义了一个克隆自身的方法,并通过该方法来创建新的对象。具体的原型类(Concrete Prototype
)实现了原型接口,并实现了克隆方法,用于创建自身的副本。
在使用原型模式时,可以将原型对象缓存在内存中,并在需要时克隆出一个全新的副本来使用。克隆分为浅克隆和深克隆两种方式。浅克隆只会克隆原型对象本身,而不会克隆其引用的对象,深克隆则会将原型对象及其引用的对象一并克隆出来。具体采用哪种方式可以根据具体情况进行选择。
总的来说,原型模式通过复制已有对象的行为来创建新的对象,减少了代码的重复工作,提高了代码的复用性和可维护性。但是需要注意的是,原型对象必须是可复制的,否则无法实现原型模式的效果。
这是一个使用 JavaScript 实现的简单的原型模式的示例:
const prototype = {name: "",getName: function() {return this.name;},setName: function(name) {this.name = name;},clone: function() {return Object.create(this);}
};const objA = Object.create(prototype);
objA.setName("Object A");const objB = objA.clone();
objB.setName("Object B");console.log(objA.getName()); // Output: "Object A"
console.log(objB.getName()); // Output: "Object B"
在这个示例中,我们先创建了一个原型对象 prototype
,它包含了属性 name
和方法 getName()
、setName()
和 clone()
。然后我们创建了一个对象 objA
,并使用 Object.create()
方法将其原型设置为 prototype
。我们调用 setName()
方法来设置 objA
的名字。接下来,我们通过调用 objA.clone()
来克隆这个对象,并将其赋值给 objB
。我们再次通过调用 setName()
来设置 objB
的名字,这一次我们输入的是 “Object B”。最后,我们分别调用 getName()
方法来获取 objA
和 objB
的名字,并将其打印出来。输出结果是 “Object A” 和 “Object B”,验证了原型模式成功工作。
相关文章:

【利用AI让知识体系化】5种创建型模式
文章目录 创建型模式简介工厂模式抽象工厂模式单例模式建造者模式原型模式 创建型模式 简介 创建型模式,顾名思义,是用来创建对象的模式。在软件开发中,对象的创建往往比一般的编程任务更为复杂,可能涉及到一些琐碎、复杂的过程…...

Unity的UnityStats: 属性详解与实用案例
UnityStats 属性详解 UnityStats 是 Unity 引擎提供的一个用于监测游戏性能的工具,它提供了一系列的属性值,可以帮助开发者解游戏的运行情况,从而进行优化。本文将详细介绍 UnityStats 的每个属性值,并提供多个使用例子帮助开发者…...

TDengine集群搭建
我这里用三台服务器搭建集群 1、如果搭建集群的物理节点上之前安装过TDengine先卸载清空,直接执行以下4条命令 rmtaos rm -rf /var/lib/taos rm -rf /var/log/taos rm -rf /etc/taos2、确保集群中所有主机开放端口 6030-6043/tcp,6060/tcp,…...

Android 12.0无源码apk设置默认启动Launcher的相关属性
1.概述 在12.0的系统产品开发中,对于一些产品的需求,需要将一些无源码app的某个MainActivity作为启动Launcher页面的功能实现,由于没有源码,所以需要 利用PMS的安装解析apk的AndroidManifest.xml的时候,在判断是某个Activity的时候,设置Lancher属性来实现某些功能 2.无源…...

js深拷贝和浅拷贝
👉十分钟学会 前端面试题 js 深拷贝与浅拷贝_前端深拷贝和浅拷贝面试题_Mar-30的博客-CSDN博客 目录 背景: 概念:核心是创建新地址 方法: 浅拷贝: Object.assign() 方法:Object.assign(拷贝的对象&am…...

CANopenNode Master 配置
文章目录 CANopenNode 简介CANopenNode 主栈SDO ClientPDO 通讯参数RPDO 通讯参数RPDO 通信参数设置实例TPDO 通讯参数TPDO 通信参数设置实例 PDO 映射参数RPDO 映射参数设置实例TPDO 映射参数设置实例 CANopenNode 简介 CANopenNode 是一个开源的免费的开源 CANopen 协议栈。…...

HW之轻量级内网资产探测漏洞扫描工具
简介 RGPScan是一款支持弱口令爆破的内网资产探测漏洞扫描工具,集成了Xray与Nuclei的Poc 工具定位 内网资产探测、通用漏洞扫描、弱口令爆破、端口转发、内网穿透、SOCK5 主机[IP&域名]存活检测,支持PING/ICMP模式 端口[IP&域名]服务扫描 网…...

算法练习-2:送外卖
n 个小区排成一列,编号为从 0 到 n-1 。一开始,美团外卖员在第0号小区,目标为位于第 n-1 个小区的配送站。 给定两个整数数列 a[0]~a[n-1] 和 b[0]~b[n-1] ,在每个小区 i 里你有两种选择: 1) 选择a:向前 a[…...

八股总结(六):Android基础:四大组件与UI控件
文章目录 Activity一个APP的启动过程基本概念总图zygote是什么?有什么作用?SystemServer是什么?有什么用,与zygote的关系是什么?为什么称为服务端对象?APP、AMS、zygote是三个独立的进程,他们之…...

【P46】JMeter 响应断言(Response Assertion)
文章目录 一、响应断言(Response Assertion) 参数说明二、准备工作三、测试计划设计3.1、包括3.2、匹配3.3、相等3.4、字符串3.5、字符串3.6、或者 一、响应断言(Response Assertion) 参数说明 可以对 Jmeter 取样器的响应消息进…...

19-02 基于业务量级的架构技术选型演进
从零开始——单服务应用 单体应用技术选型 (GitHub、Gitee…)搜索是否有线程的产品用最熟悉的技术,最快的速度上线如果有经费:考虑商业化解决方案 个人小程序怎么做技术选型的 搜索是否有快速搭建下程序的软件技术选型 后端技…...

Server - 高性能的 PyTorch 训练环境配置 (PyTorch3D 和 FairScale)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/130863537 PyTorch3D 是基于 PyTorch 的 3D 数据深度学习库,提供了高效、模块化和可微分的组件,以简化 3D 深度学…...

小猫踩球-第14届蓝桥杯省赛Scratch中级组真题第2题
[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第137讲。 小猫踩球,本题是2023年5月7日举行的第14届蓝桥杯省赛Scratch图形化编程中级组真题第2题…...

嵌入式开发从入门到精通之第二十一节:三轴加速度传感器(BMA250E)
目录 1、工作模式 2、中断支持的模式 2.1 新数据的产生 2.2 任何斜率的变化的监测...

代码随想录算法训练营第三十六天|435. 无重叠区间 763.划分字母区间 56. 合并区间
目录 LeeCode 435. 无重叠区间 LeeCode 763.划分字母区间 LeeCode 56. 合并区间 LeeCode 435. 无重叠区间 435. 无重叠区间 - 力扣(LeetCode) 思路1:按照右边界排序,从左向右记录非交叉区间的个数。最后用区间总数减去非交叉…...

shell 脚本
Shell概述 shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核 脚本入门 脚本格式 脚本以#!/bin/bash开头(指定解析器) helloworld # 创建脚本 [linuxlocalhost datas]$ cat helloworld.sh #!/bin/bas…...

Linux :: 【基础指令篇 :: 用户管理(补充):(4)】::用户切换
前言:本篇是 Linux 基本操作篇章的内容! 笔者使用的环境是基于腾讯云服务器:CentOS 7.6 64bit。 学习集: C 入门到入土!!!学习合集Linux 从命令到网络再到内核!学习合集 目录索引&am…...

打印机无法扫描的原因及解决方法
在家庭和办公环境中,打印机已成为不可或缺的设备。它不仅可以打印文件,还可以扫描文档并将它们转换为数字数据。但有时,打印机可能无法扫描文档或图片。以下是可能导致这些问题的原因和解决方法。 出现打印机无法扫描的原因: 1.…...

【Mysql】 数据类型
文章目录 【Mysql】 数据类型数据类型分类数值类型1. tinyint类型2. bit类型3. 小数类型 字符串类型1.char2.varchar3. 日期和时间类型4. enum 和 set 【Mysql】 数据类型 mysql中数据类型的作用: 约束操作者的行为更清晰的代码逻辑不同的功用 – 例如,…...

mysql中如何使用乐观锁和悲观锁
MySQL中可以使用SELECT ... FOR UPDATE语句来实现悲观锁。这个语句会在查询时锁定被查询的行,在事务结束前都不会释放锁。 例如,我们可以使用以下的 SQL 语句来锁定一个特定的行: BEGIN; SELECT * FROM table WHERE id 1 FOR UPDATE; ... C…...

Logstash技术栈总结
Logstash 是一个可以传输和处理你的日志、事务或其他数据的功能强大的工具,可与各种部署集成。 它提供了大量插件,可帮助你解析,丰富,转换和缓冲来自各种来源的数据。 工作原理 Logstash 事件处理有三个阶段:inputs …...

解决:在单项目组件里面引入 base.scss/ base.less 等的外部文件不成功的问题
1、问题展示: 其一、问题描述: 在单文件组件里面使用封装在 base.scss 或 base.less 里面的样式用法一直不成功; 其二、代码: // 虽然已经标明了用的是 scss 的语法,但是页面调用 .scss 里的 style 样式还是不成功&a…...

论文分享 | WSBERT:Weighted Sampling for Masked Language Modeling
本次分享阿里巴巴达摩院语音实验室、新南威尔士大学与香港科技大学(广州)等在ICASSP2023会议发表的论文《Weighted Sampling for Masked Language Modeling》。该论文主要提出了两种简单有效的加权采样策略,来缓解掩码语言模型(ML…...

java 在线音乐网站系统Myeclipse开发mysql数据库struts2结构java编程计算机网页项目
一、源码特点 java 在线音乐网站系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助struts2开发技术,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mys…...

软件测试基础教程学习1
文章目录 软件测试概述1.1 什么是软件测试1.2 软件测试的目的1.3 对软件测试的理解1.4 软件测试的原则1.5 测试人员的职责1.6 测试人员的素质要求 软件测试概述 1.1 什么是软件测试 1)软件测试要发现软件的错误。 2)软件测试最终要以软件满足用户需求为…...

浅谈一下@Async和SpringSecurityContext可能会遇到的问题和解决方案
Async和SpringSecurityContext 场景回溯 在执行一个用时较长的批量插入业务的时候,我尝试使用Async异步对业务进行优化,但是却给我报了空指针的错误,定位之后发现 此处我是基于SpringSecurity来获取用户的 是currentUserService获取到的当前登陆用户为空导致的,但是当前确实是…...

VUE常见面试题
1.为什么要使用Vue? 答:Vue是一款优秀的前端框架,它可以帮助我们快速构建高效、可复用、易维护的Web应用程序,并提供了丰富的API和生态系统。 2. Vue有哪些生命周期钩子函数? 答:Vue有8个生命周期钩子函…...

字符串匹配算法--KMP算法--BM算法
该算法解决的是字符串匹配问题,即查看字符串中是否含有完整的匹配字符串。如在java的string的contains方法匹配问题最简单的就是暴力破解了。在java的contains也是这么实现的,效率是低一点的。如果想要更快的速度可以自己写KMP算法。 代码实现体验 Knut…...

swagger的简单介绍
目录 swagger是什么? swagger有什么用? Swagger包含的工具集: swagger的使用步骤: swagger的相关注解: Docket的源码 了解swagger的作用和概念了解前后端分离在SpringBoot中集成Swagger swagger是什么?…...

HNU-电路与电子学-小班3
第三次讨论 1 、直接用晶体管而不是逻辑门实现异或门,并解释这个电路是如何工作的。 (6个 MOS 管构成) 2 、通信双方约定采用 7 位海明码进行数据传输。请为发送方设计海明码校验位 生成电路,采用功能块和逻辑门为接收方设计海…...