设计模式(工厂模式,模板方法模式,单例模式)

单例模式:

确保一个类只有一个实例,并提供全局访问点。

单例模式举例:

  1. 配置信息类:用于存储应用程序的全局配置信息,例如数据库连接信息、日志配置等。

  2. 日志类:用于记录应用程序运行时的日志信息,确保在整个应用程序中只有一个日志实例

  3. 线程池类:在多线程环境下,使用单例模式可以确保只有一个线程池实例,提高资源利用率和性能。

单例模式饿汉式:

代码:

public class Singleton {/*防止外界随意使用构造方法new对象,我们需要将构造私有化*/private Singleton(){}/*为了赶紧new对象,我们new对象的时候变成静态的,让其随着类的加载而加载为了不让外界随便使用类名调用此静态对象,我们将其变成private*/private static Singleton singleton = new Singleton();/*为了将内部new出来的对象给外界我们可以定义 一个方法,将内部的对象返回给外界*/public static Singleton getSingleton(){return singleton;}
}

将new出来的对象设置为静态属性,这样随着类的加载而加载

单例模式懒汉式:

public class Singleton1 {/*防止外界随意使用构造方法new对象,我们需要将构造私有化*/private Singleton1() {}/*懒汉式,不着急new对象*/private static Singleton1 singleton1 = null;/*为了将内部new出来的对给外界定义一个方法,将内部new出来的对返回*/public static Singleton1 getSingleton1() {//如果singleton1不是null就没必要抢锁了,直接返回,是null再抢锁if (singleton1==null){synchronized (Singleton1.class){if (singleton1 == null) {singleton1 = new Singleton1();}}}return singleton1;}
}

懒汉式就不着急new对象了,留了一个公共的接口,你想new的时候就new即可

懒汉式的线程不安全问题:

这也是懒汉式的一个缺点:如果没有加锁的代码:

public static Singleton1 getSingleton1() {if (singleton1 == null) {singleton1 = new Singleton1();}return singleton1;}

这很容易引发线程不安全问题,我们设想有两个线程,第一个线程需要这个singleton1这个对象,进入了if判断,不过这个时候CPU将线程切换给了第二个线程,那这个时候,第二个线程也进入了if判断,然后CPU再切换会第一个线程,线程一创建了对象,但是我们知道线程二也进入了if判断,它也能创建对象,这就导致了线程不安全问题

饿汉式和懒汉式区别:

1:创建的时间不一样:饿汉式是在类加载过程中就创建了实例,而饿汉式是被调用的时候才创建实例

2:线程安全问题:饿汉式不存在什么线程安全,类加载的时候我就创建了,而且不能改,不可能又线程安全问题,反观饿汉式就有线程安全问题

在Spring中的单例模式的体现:

 在 Spring 源码中,最常见的使用单例设计模式的场景就是在创建 Bean 实例时使用单例模式。Spring 容器默认情况下会将所有的 Bean 对象作为单例对象进行管理,这样可以节省资源,提高性能。

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);@Overridepublic Object getSingleton(String beanName) {return this.singletonObjects.get(beanName);}@Overridepublic void registerSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {Object oldObject = this.singletonObjects.get(beanName);if (oldObject != null) {throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName +"': there is already object [" + oldObject + "] bound");}this.singletonObjects.put(beanName, singletonObject);}}// 其他方法...
}

这个是我在鱼皮公众号上看到的,我第一次看到这段话的时候,也是有一个疑问

创建 Bean 实例是饿汉式还是懒汉式?

然后我问了GPT:

Spring容器在启动时会预先实例化所有单例Bean对象,这样可以避免懒汉式中可能存在的线程安全问题,确保在需要使用Bean时能够立即获取到对象实例。这种预先实例化的方式类似于饿汉式,但并不完全等同于饿汉式的实现方式。


模板方法模式:

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。明确了一部分功能,而另一部分功能不明确。需要延伸到子类中实现

 这个我觉得就非常好理解:

我们平常都在写的接口或者抽象类都是这种思想

比如我们要去餐馆吃饭,我们每次餐馆都要点菜买单

不过我们去不同的餐馆点的菜都不一样

就可以把餐馆抽象成一个类,不同的餐馆都是实现类

上一段代码:

public abstract class Hotel {public void eat(){System.out.println("点菜");eatCai();System.out.println("买单");}public abstract void eatCai();
}public class QuanJuDe extends Hotel{@Overridepublic void eatCai() {System.out.println("薄饼");System.out.println("放鸭肉");System.out.println("酱");System.out.println("葱丝");System.out.println("黄瓜丝");System.out.println("卷着吃");}
}
public class ZhangLiang extends Hotel{@Overridepublic void eatCai() {System.out.println("调麻酱");System.out.println("放辣椒油");System.out.println("倒到大碗中吃");}
}public class Test01 {public static void main(String[] args) {QuanJuDe quanJuDe = new QuanJuDe();quanJuDe.eat();System.out.println("================");ZhangLiang zhangLiang = new ZhangLiang();zhangLiang.eat();}
}

 


工厂模式:

工厂模式是一种创建型设计模式,其主要目的是封装对象的实例化过程,将对象的创建和使用分离。通过工厂模式,可以实现更灵活、可扩展的对象创建方式,同时降低代码的耦合度。

工厂模式分为下面三种:简单工厂模式,工厂方法模式,抽象工厂模式


还没有工厂的时候:我们如果需要车,我们得自己去造车 自己去 new 对象
public class BMW320 {public BMW320(){System.out.println("制造-->BMW320");}
}public class BMW523 {public BMW523(){System.out.println("制造-->BMW523");}
}public class Customer {public static void main(String[] args) {BMW320 bmw320 = new BMW320();BMW523 bmw523 = new BMW523();}
}
简单工厂模式:简单工厂的时候,我们已经有了简单的工厂,我们不用自己去造车了

我们可以告诉工厂,我们需要这个这个车,工厂造好给我们即可

有一个工厂类,我们去调用工厂类的造车方法造车

产品类:

// 产品接口
interface Product {void doSomething();
}// 具体产品类 A
class ConcreteProductA implements Product {@Overridepublic void doSomething() {System.out.println("Product A is doing something.");}
}// 具体产品类 B
class ConcreteProductB implements Product {@Overridepublic void doSomething() {System.out.println("Product B is doing something.");}
}

工厂类: 

// 简单工厂类
class SimpleFactory {public static Product createProduct(String type) {if ("A".equals(type)) {return new ConcreteProductA();} else if ("B".equals(type)) {return new ConcreteProductB();}return null;}
}

客户端代码:

// 客户端代码
public class Main {public static void main(String[] args) {Product productA = SimpleFactory.createProduct("A");productA.doSomething();Product productB = SimpleFactory.createProduct("B");productB.doSomething();}
}
工厂方法模式:到了这个时候,随着车型的增多,一个工厂已经不能生成这么多车型了

就需要工厂分类:每个工厂生成一种型号的车

有一个工厂抽象类,生成各种型号的车的工厂去继承里面的造车方法

再有一个车的抽象类,不同的车去继承里面的方法
 

 

// 产品接口
interface Product {void doSomething();
}// 具体产品类 A
class ConcreteProductA implements Product {@Overridepublic void doSomething() {System.out.println("Product A is doing something.");}
}// 具体产品类 B
class ConcreteProductB implements Product {@Overridepublic void doSomething() {System.out.println("Product B is doing something.");}
}// 工厂接口
interface Factory {Product createProduct();
}// 具体工厂类 A,负责创建产品 A
class ConcreteFactoryA implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}// 具体工厂类 B,负责创建产品 B
class ConcreteFactoryB implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductB();}
}// 客户端代码
public class Main {public static void main(String[] args) {Factory factoryA = new ConcreteFactoryA();Product productA = factoryA.createProduct();productA.doSomething();Factory factoryB = new ConcreteFactoryB();Product productB = factoryB.createProduct();productB.doSomething();}
}
抽象工厂模式:这个时候的需求就已经很复杂了,

每个车需要的零件都不同,比如车1和车2分别是两个不同的型号,车1需要空调a和发动机b,车2需要空调b和发动机b

这个时候就设计到了一个产品族,就是空调,发动机或者其它产品合在一起就是一个产品族

有点像我们日常生活中开店,比如我们开冷冻产品店,那我们不可能一个人去准备所有的冷冻产品,我肯定是去找对应的供货商,比如火锅料的供货商,鱿鱼的供货商,饮料的供货商,然后整合到我这个冷冻店再去销售

所以翻译成Java语言就是,空调是一个抽象类,发动机是一个抽象类,多个抽象类,一个工厂抽象类,不同型号的车是一个类都去继承这个工厂,你需要什么零件就去这个工厂里面配这个零件。

// 产品族接口
interface AbstractProductA {void doSomething();
}interface AbstractProductB {void doSomething();
}// 具体产品类 A1
class ConcreteProductA1 implements AbstractProductA {@Overridepublic void doSomething() {System.out.println("Product A1 is doing something.");}
}// 具体产品类 B1
class ConcreteProductB1 implements AbstractProductB {@Overridepublic void doSomething() {System.out.println("Product B1 is doing something.");}
}// 具体产品类 A2
class ConcreteProductA2 implements AbstractProductA {@Overridepublic void doSomething() {System.out.println("Product A2 is doing something.");}
}// 具体产品类 B2
class ConcreteProductB2 implements AbstractProductB {@Overridepublic void doSomething() {System.out.println("Product B2 is doing something.");}
}// 抽象工厂接口
interface AbstractFactory {AbstractProductA createProductA();AbstractProductB createProductB();
}// 具体工厂类 1
class ConcreteFactory1 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ConcreteProductA1();}@Overridepublic AbstractProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂类 2
class ConcreteFactory2 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ConcreteProductA2();}@Overridepublic AbstractProductB createProductB() {return new ConcreteProductB2();}
}// 客户端代码
public class Main {public static void main(String[] args) {AbstractFactory factory1 = new ConcreteFactory1();AbstractProductA productA1 = factory1.createProductA();AbstractProductB productB1 = factory1.createProductB();productA1.doSomething();productB1.doSomething();AbstractFactory factory2 = new ConcreteFactory2();AbstractProductA productA2 = factory2.createProductA();AbstractProductB productB2 = factory2.createProductB();productA2.doSomething();productB2.doSomething();}
}

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

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

相关文章

HTML5实现好看的天气预报网站源码

文章目录 1.设计来源1.1 获取天气接口1.2 PC端页面设计1.3 手机端页面设计 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_4…

揭秘电子画册制作流程,打造独一无二的作品

在这个数字化的时代&#xff0c;电子画册已经成为了展示个人创意和品牌形象的重要工具。它不仅能够呈现出丰富多彩的内容&#xff0c;还能够实现互动性和传播性&#xff0c;吸引众多观众的目光。然而&#xff0c;许多人对于电子画册的制作流程仍然感到陌生。本文将揭秘电子画册…

企业VR展厅如何提升品牌形象,生动展示产品和企业文化?

一、提升产品展示效果 1、全方位展示产品细节 企业VR展厅可以通过3D建模和虚拟现实技术&#xff0c;将产品的每一个细节清晰地展示出来。客户可以全方位查看产品的外观、结构和功能。这种身临其境的体验远比传统的平面展示更加生动和详细。 细节展示&#xff1a;客户可以通过…

Ubuntu22 Qt6.6 ROS 环境搭建

Ubuntu22.04; Qt6.6; Qt Creator 13.01; ROS2 1. 安装 Qt ROS 插件 1.下载地址&#xff1a; https://github.com/ros-industrial/ros_qtc_plugin/releases 选择对应 Qt Creator 版本的安装包。 2. Qt Creator中&#xff0c;“Help - 关于插件”–>“install Plugin…

一个模板实现的工厂的编译问题的解决。牵扯到重载、特化等

简介 在一个项目里&#xff0c;调用了第三封的库&#xff0c;这个库里面有个类用的很多&#xff0c;而且其构造函数至少有6个&#xff0c;并且个人感觉还不够多。根据实际使用&#xff0c;还得增加一些。 需求 1、增加构造函数&#xff0c;比如除了下面的&#xff0c;还增加…

Gateway源码分析:路由Route、断言Predicate、Filter

文章目录 源码总流程图说明GateWayAutoConfigurationDispatcherHandlergetHandler()handleRequestWith()RouteToRequestUrlFilterReactiveLoadBalancerClientFilterNettyRoutingFilter 补充知识适配器模式 详细流程图 源码总流程图 在线总流程图 说明 Gateway的版本使用的是…

01常见控件

文章目录 控件各种响应事件获取控件类型CButton/CheckBox&#xff08;多选&#xff09;/RadioButton&#xff08;单选&#xff09;EditControl&#xff08;文本编辑框&#xff09;/ ListBox&#xff08;列表文本框&#xff09;/ComboBox&#xff08;可下拉列表&#xff09;Prog…

es master 节点数据丢失导致数据节点加入集群失败的灾难恢复

文章目录 [toc]前情提要解决方案解决流程实践过程停止 es 节点master 节点增加数据持久化新建 es-node-tools pod使用 elasticsearch-node 命令dangling 悬空索引 前情提要 部署的架构可以看我之前的博客&#xff1a;k8s 使用 helm 文件部署 8.12.2 es 分角色集群&#xff0c;当…

【软考】UML中的关联关系

目录 一、说明二、具体类型2.1 普通关联2.2 单向关联2.3 双向关联2.4 自关联2.4 聚合关系&#xff08;Aggregation&#xff09;2.5 组合关系&#xff08;Composition&#xff09; 三、关联关系中的多重性 一、说明 1.UML&#xff08;Unified Modeling Language&#xff0c;统一…

【Ubuntu】Ubuntu系统镜像

清华镜像源 Index of /ubuntu-releases/ | 清华大学开源软件镜像站 | Tsinghua Open Source MirrorIndex of /ubuntu-releases/ | 清华大学开源软件镜像站&#xff0c;致力于为国内和校内用户提供高质量的开源软件镜像、Linux 镜像源服务&#xff0c;帮助用户更方便地获取开源软…

测开知识点合集2

一、try .... catch.. AccessViolationException异常触发后&#xff0c;下列程序的输出结果为 static void Main(string[] args) { try { throw new AccessViolationException(); Console.WriteLine("error1"); } catch (Exception e) { Console.WriteLi…

stm32学习:(寄存器2)GPIO总体说明

目录 GPIO的主要特点 GPIO的8种工作模式 GPIO电路结构 GPIO输出模式 输出流程 复用输出模式 GPIO输入模式 输入流程 模拟输入流程 GPIO相关的7个寄存器 GPIOx_CRL GPIOx_CRH GPIOx_IDR GPIOx_ODR GPIOx_BSRR GPIOx_BRR GPIOx_LCKR 实例 三个灯流水灯 main.…

C语言基础 9. 指针

C语言基础 9. 指针 文章目录 C语言基础 9. 指针9.1. &9.2. 指针9.3. 指针的使用9.4. 指针与数组9.5. 指针与const9.6. 指针运算9.7. 动态内存分配 9.1. & 运算符&: scanf(“%d”, &i);里的& 获得变量的地址, 它的操作数必须是变量 int i;printf(“%x”, &…

CSS中如何实现鼠标悬停效果?

在CSS中&#xff0c;您可以使用:hover伪类来实现鼠标悬停效果。:hover伪类会在用户将鼠标悬停在选择器所匹配的元素上时应用指定的样式。 下面是一个简单的例子&#xff0c;展示了如何在鼠标悬停时改变文本颜色和背景颜色&#xff1a; <!DOCTYPE html> <html lang&qu…

【SpringBoot Web开发之静态资源访问】笔记

详细内容见官方文档&#xff1a;Static Content SpringBoot Web开发之静态资源访问 1.准备工作&#xff1a;创建WebDemo2.静态资源目录2.1官网原文2.2静态资源目录第一步&#xff1a;依照上面2.1官网原文中创建如下目录第二步&#xff1a;复制粘贴图片到静态资源目录中第三步…

MySQL:JOIN 多表查询

多表查询 在关系型数据库中&#xff0c;表与表之间是有联系的&#xff0c;它们通过 外键 联系在一起&#xff0c;所以在实际应用中&#xff0c;经常使用多表查询。多表查询就是同时查询两个或两个以上的表。 MySQL多表查询是数据库操作中非常重要的一部分&#xff0c;它允许你…

Pandas 33个冷知识 0721

Pandas 33个冷知识 从Excel读取数据: 使用 pd.read_excel(file.xlsx) 来读取Excel文件。 写入Excel: 使用 df.to_excel(file.xlsx, indexFalse) 将DataFrame写入Excel文件。 创建日期索引: 使用 df.set_index(pd.to_datetime(df[date])) 创建日期索引。 向后填充缺失值: 使用…

【深入理解SpringCloud微服务】浅析微服务注册中心Eureka与nacos,手写实现一个微服务注册中心

【深入理解SpringCloud微服务】浅析微服务注册中心Eureka与nacos&#xff0c;手写实现一个微服务注册中心 注册中心手写实现一个注册中心服务端设计客户端设计 注册中心 注册中心是微服务体系里面非常重要的一个核心组件&#xff0c;它最重要的作用就是实现服务注册与发现。 …

【MyBatisPlus】快速掌握MP插件使用方法

一、MyBatis-Plus简介 1.1 简介 1.2 特性 无侵入&#xff1a;只做增强不做改变&#xff0c;引入它不会对现有工程产生影响&#xff0c;如丝般顺滑损耗小&#xff1a;启动即会自动注入基本 CURD&#xff0c;性能基本无损耗&#xff0c;直接面向对象操作强大的 CRUD 操作&#x…

【ACM独立出版|EI检索稳定】2024年智能感知与模式识别国际学术会议(ISPC 2024,9月6日-8)

2024年智能感知与模式识别国际学术会议 (ISPC 2024)将于2024年9月6日-8日于中国青岛召开。 会议将围绕智能感知与模式识别等领域中的最新研究成果&#xff0c;为来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、工程师等提供一个分享专业经验&#xff0c;扩大…