设计模式使用场景实现示例及优缺点(创建型模式——单例模式、建造者模式、原型模式)

创建型模式

单例模式(Singleton Pattern)

单例模式(Singleton Pattern)在Java中的使用场景与在其他编程语言中类似,其主要目的是确保一个类只有一个实例,并提供一个全局的访问点。以下是单例模式的一些常见使用场景及详细讲解:

使用场景

  1. 控制资源的使用

    • 数据库连接池:数据库连接是昂贵的资源,使用单例模式可以确保只有一个连接池实例,统一管理连接资源,避免重复创建和销毁连接,提高系统性能。
    • 线程池:线程的创建和销毁开销较大,单例模式可以确保只有一个线程池实例,集中管理线程,提高系统效率。
  2. 全局配置管理

    • 配置文件管理:系统中的配置通常是全局的,使用单例模式可以确保配置文件只被加载一次,并且全局共享,避免多次加载造成的资源浪费。
    • 日志管理器:日志系统在应用程序中通常是全局的,通过单例模式可以确保日志管理器实例的唯一性,方便统一管理日志输出。
  3. 状态管理

    • 缓存管理:在某些系统中,需要对一些数据进行缓存,使用单例模式可以确保缓存管理器实例的唯一性,从而保证缓存的一致性和统一管理。
    • 设备管理:对于一些物理设备,如打印机或串口设备,通过单例模式可以确保设备管理器的唯一实例,避免设备被多个对象同时操作。

实现示例(Java)

下面是一个在Java中实现单例模式的示例:

饿汉式单例模式

饿汉式单例模式在类加载时就创建实例:

public class Singleton {// 在类加载时创建实例private static final Singleton INSTANCE = new Singleton();// 私有化构造函数,防止外部实例化private Singleton() {}// 提供一个公共的访问方法public static Singleton getInstance() {return INSTANCE;}
}
懒汉式单例模式

懒汉式单例模式在需要时才创建实例:

public class Singleton {// 初始时不创建实例private static Singleton instance;// 私有化构造函数,防止外部实例化private Singleton() {}// 提供一个公共的访问方法,并使用 synchronized 关键字确保线程安全public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}
双重检查锁定(Double-Checked Locking)

这种方式通过双重检查加锁,确保线程安全并提高效率:

public class Singleton {// 使用 volatile 关键字确保多线程环境下变量的可见性private static volatile Singleton instance;// 私有化构造函数,防止外部实例化private Singleton() {}// 提供一个公共的访问方法public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}

使用示例

public class Main {public static void main(String[] args) {Singleton singleton1 = Singleton.getInstance();Singleton singleton2 = Singleton.getInstance();singleton1.value = 42;System.out.println(singleton2.value); // 输出 42,证明两个引用指向同一个实例}
}

通过上述示例,可以看出无论是饿汉式、懒汉式还是双重检查锁定,单例模式都可以确保一个类只有一个实例,并在需要时提供全局访问点。这在实际应用中有助于资源管理、状态管理和配置管理等。

建造者模式(Builder Pattern)

建造者模式(Builder Pattern)是一种创建型设计模式,它允许你分步骤创建复杂对象。通过将一个复杂对象的构造代码从其表示中分离出来,建造者模式可以让你通过细化各个部分的构造步骤来创建一个复杂对象。

适用场景

  1. 需要生成的对象有复杂的内部结构

    • 对象的创建过程包含多个步骤或多个部件的创建。
  2. 同样的创建过程需要生成不同的表示

    • 一个构建过程可以创建多个不同类型的对象。
  3. 客户端代码不希望直接控制对象的创建过程

    • 客户端代码只需要一个构建器来控制创建的细节。

实现示例(Java)

以下是一个简单的建造者模式的实现示例,展示如何创建不同类型的房子(如石头房子和木头房子)。

1. 产品类
public class House {private String foundation;private String structure;private String roof;private String interior;public void setFoundation(String foundation) {this.foundation = foundation;}public void setStructure(String structure) {this.structure = structure;}public void setRoof(String roof) {this.roof = roof;}public void setInterior(String interior) {this.interior = interior;}@Overridepublic String toString() {return "House [foundation=" + foundation + ", structure=" + structure + ", roof=" + roof + ", interior=" + interior + "]";}
}
2. 抽象建造者类
public abstract class HouseBuilder {protected House house;public House getHouse() {return house;}public void createNewHouse() {house = new House();}public abstract void buildFoundation();public abstract void buildStructure();public abstract void buildRoof();public abstract void buildInterior();
}
3. 具体建造者类
public class StoneHouseBuilder extends HouseBuilder {@Overridepublic void buildFoundation() {house.setFoundation("Stone foundation");}@Overridepublic void buildStructure() {house.setStructure("Stone walls");}@Overridepublic void buildRoof() {house.setRoof("Stone roof");}@Overridepublic void buildInterior() {house.setInterior("Stone interior");}
}public class WoodenHouseBuilder extends HouseBuilder {@Overridepublic void buildFoundation() {house.setFoundation("Wooden foundation");}@Overridepublic void buildStructure() {house.setStructure("Wooden walls");}@Overridepublic void buildRoof() {house.setRoof("Wooden roof");}@Overridepublic void buildInterior() {house.setInterior("Wooden interior");}
}
4. 指挥者类
public class Director {private HouseBuilder houseBuilder;public void setHouseBuilder(HouseBuilder houseBuilder) {this.houseBuilder = houseBuilder;}public House getHouse() {return houseBuilder.getHouse();}public void constructHouse() {houseBuilder.createNewHouse();houseBuilder.buildFoundation();houseBuilder.buildStructure();houseBuilder.buildRoof();houseBuilder.buildInterior();}
}
5. 客户端代码
public class Client {public static void main(String[] args) {Director director = new Director();// 建造石头房子HouseBuilder stoneHouseBuilder = new StoneHouseBuilder();director.setHouseBuilder(stoneHouseBuilder);director.constructHouse();House stoneHouse = director.getHouse();System.out.println("House built:\n" + stoneHouse);// 建造木头房子HouseBuilder woodenHouseBuilder = new WoodenHouseBuilder();director.setHouseBuilder(woodenHouseBuilder);director.constructHouse();House woodenHouse = director.getHouse();System.out.println("House built:\n" + woodenHouse);}
}

注释说明

  1. 产品类

    • House 类表示一个复杂对象。它有多个部件(如基础、结构、屋顶和内部装饰)。
  2. 抽象建造者类

    • HouseBuilder 是一个抽象类,定义了构建 House 对象的各个步骤(如 buildFoundationbuildStructure 等)。
  3. 具体建造者类

    • StoneHouseBuilderWoodenHouseBuilder 是具体的建造者类,实现了抽象建造者类的方法,具体定义了如何构建 House 的各个部件。
  4. 指挥者类

    • Director 类负责管理建造过程。它通过调用 HouseBuilder 的方法来一步步构建 House 对象。
  5. 客户端代码

    • Client 类通过 Director 类来构建不同类型的房子。客户端代码不需要直接控制对象的创建过程,只需要使用 Director 来管理建造者。

总结

建造者模式通过将复杂对象的构建过程分离出来,使得客户端代码可以灵活地构建不同类型的对象。它适用于需要构建复杂对象的场景,尤其是当对象的创建过程包含多个步骤或多个部件时。建造者模式可以提高代码的可读性和可维护性。

原型模式(Prototype Pattern)

原型模式(Prototype Pattern)是一种创建型设计模式,它允许一个对象通过克隆自身来创建新的对象。使用原型模式,可以避免创建对象时涉及复杂的初始化步骤,同时也可以方便地复制已有对象的状态。

适用场景

  1. 对象的创建成本很高

    • 当对象的创建成本很高,且可以通过复制来减少成本时,可以使用原型模式
  2. 对象的初始化复杂

    • 对象的初始化需要很多步骤,而这些步骤又可能会有所变化,使用原型模式可以简化这些步骤。
  3. 需要大量相似对象

    • 当需要大量相似对象时,可以通过复制原型来快速创建新对象。

实现示例(Java)

以下是一个简单的原型模式的实现示例,展示如何克隆不同类型的形状(如圆形和矩形)。

1. 定义原型接口
public interface Shape extends Cloneable {Shape clone();void draw();
}
2. 具体原型类实现接口
public class Circle implements Shape {private int radius;public Circle(int radius) {this.radius = radius;}@Overridepublic Circle clone() {return new Circle(this.radius);}@Overridepublic void draw() {System.out.println("Drawing a circle with radius: " + radius);}
}public class Rectangle implements Shape {private int width;private int height;public Rectangle(int width, int height) {this.width = width;this.height = height;}@Overridepublic Rectangle clone() {return new Rectangle(this.width, this.height);}@Overridepublic void draw() {System.out.println("Drawing a rectangle with width: " + width + " and height: " + height);}
}
3. 客户端代码
public class Client {public static void main(String[] args) {// 创建原型对象Circle originalCircle = new Circle(5);Rectangle originalRectangle = new Rectangle(3, 4);// 克隆对象Circle clonedCircle = originalCircle.clone();Rectangle clonedRectangle = originalRectangle.clone();// 使用克隆对象originalCircle.draw();clonedCircle.draw();originalRectangle.draw();clonedRectangle.draw();}
}

注释说明

  1. 原型接口

    • Shape 接口继承了 Cloneable 接口,并定义了 clonedraw 方法。clone 方法用于克隆对象,draw 方法用于绘制形状。
  2. 具体原型类

    • CircleRectangle 类实现了 Shape 接口,并提供了自己的 clonedraw 方法。
    • clone 方法使用当前对象的状态创建一个新对象。
  3. 客户端代码

    • Client 类创建了原型对象(如 CircleRectangle),然后通过调用 clone 方法克隆这些对象,并使用克隆的对象。

总结

原型模式通过克隆现有对象来创建新对象,适用于对象创建成本高、初始化复杂或需要大量相似对象的场景。它能够简化对象创建过程,提高代码的灵活性和可维护性。


http://www.ppmy.cn/devtools/58928.html

相关文章

苹果电脑玩游戏咋样 苹果电脑能玩什么游戏 mac支持的steam游戏 好玩的苹果电脑游戏推荐

随着苹果电脑在全球范围内的普及,越来越多的用户开始关注Mac平台上可玩的游戏。幸运的是,Steam作为最大的数字发行平台之一,提供了大量适用于Mac操作系统的游戏。无论你是喜欢策略、冒险还是射击类游戏,都能在Steam上找到适合自己…

Django 实现子模版继承父模板

背景 Django的占位符,如果不继承父模板的内容,会被子模版所覆盖,有些业务场景子模版也需要使用到父模板中的内容 可以使用Django自带的标签{% block super %}来实现此效果 base.html 最基础html,相当于第一层html,bl…

Selenium使用注意事项:

find_element 和 find_elements 的区别 WebDriver和WebElement的区别 问题: 会遇到报错: selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector",&…

Linux Vim全面教程

引言 Vim,源自Vi IMproved,是一个高度可配置的文本编辑器,用于创建和修改任何类型的文本。它是自由软件,可在大多数Unix系统和Linux发行版中找到。 Vim的模式 Vim有多种模式,但主要分为以下几种: 普通模…

数据库db文件损坏修复方法(sqlite3:database disk image is malformed)

参考博客: https://www.cnblogs.com/liuyangQAQ/p/18037546 sqlite3数据库提示database disk image is malformed 解决办法-CSDN博客 【SQL】sqlite数据库损坏报错:database disk image is malformed(已解决)-CSDN博客 一、第…

Perl 语言进阶学习

Perl 语言进阶学习 在掌握 Perl 的基础知识后,进一步学习 Perl 的高级特性和应用,将有助于提升编程效率和解决复杂问题的能力。本文将详细介绍 Perl 语言的高级功能、最佳实践以及实际应用案例。 目录 高级数据结构 多维数组复杂数据结构 引用与匿名数…

组合模式(大话设计模式)C/C++版本

组合模式 C #include <iostream> #include <list> using namespace std; // 公司类... 抽象或者接口 class Company { public:Company(string name){this->name name;}virtual void Add(Company *c) 0; // 增加virtual void Remove(Company *c) 0; // 移…

什么是面向对象编程

什么是面向对象编程&#xff1f;&#xff08;OOP&#xff09; ● 面向对象编程是一种基于对象概念的编程范式&#xff1b;&#xff08;所谓的编程范式&#xff0c;就是代码风格&#xff0c;我们“如何”编写和组织代码&#xff09;&#xff1b; ● 我们使用对象来模拟&#xf…

4. kvm存储虚拟化

kvm存储虚拟化 一、命令行工具管理虚拟磁盘1、查看虚拟磁盘2、添加磁盘3、删除磁盘 二、qcow2格式的磁盘文件1、创建磁盘文件2、差量镜像/快速创建虚机2.1 创建差量镜像2.2 准备配置文件2.3 创建虚拟机2.4 批量部署虚拟机 三、存储池 storage pool1、类型2、在线迁移2.1 规划后…

Python爬虫之路(2):爬天气情况

hello hello~ &#xff0c;这里是绝命Coding——老白~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff1a;绝命Coding-CSDN博客 &a…

国产精品ORM框架-SqlSugar详解 进阶功能 集成整合 脚手架应用 专题二

国产精品ORM框架-SqlSugar详解 SqlSugar初识 专题一-CSDN博客 sqlsugar 官网-CSDN博客 4、进阶功能 5、集成整合 6、脚手架应用 4、进阶功能 4.1、生命周期 Queryable 什么时候操作库 Queryable是一个引用类型 Queryable拷贝机制 4.2、执行Sql 方法列表 方法名 描述 返…

pytest系列——pytest_runtest_makereport钩子函数获取测试用例执行结果

前言 pytest测试框架提供的很多钩子函数方便我们对测试框架进行二次开发&#xff0c;可以根据自己的需求进行改造。 例如&#xff1a;钩子方法&#xff1a;pytest_runtest_makereport &#xff0c;可以更清晰的了解测试用例的执行过程&#xff0c;并获取到每个测试用例的执行…

简易限流实现

需求描述 写一个1秒两个的限流工具类&#xff0c;2r/s 使用semaphore 代码实现-类似令牌桶算法 public class LimitHelper {private int maxLimit;private Semaphore semaphore;private int timeoutSeconds;public LimitHelper(int maxLimit, int timeoutSeconds) {this.max…

单网口设备的IP地址识别-还原-自组网

1.如果知道该设备所在网段&#xff1a; 此时可以使用nmap工具&#xff0c;进行网段扫描&#xff1a; nmap -sn 192.168.0.0/24 256个地址的子网10秒就能扫描一轮。关掉设备&#xff0c;打开设备&#xff0c;diff&#xff0c;基本就可以定位所要找到目标设备的IP 2.如果不知道…

Spark SQL中的正则表达式应用

正则表达式是一种强大的文本处理工具,在Spark SQL中也得到了广泛支持。本文将介绍Spark SQL中使用正则表达式的主要方法和常见场景。 目录 1. 正则表达式函数1.1 regexp_extract1.2 regexp_replace1.3 regexp_like 2. 在WHERE子句中使用正则表达式3. 在GROUP BY中使用正则表达…

晏子春秋-读书笔记二

“橘生淮南则为橘&#xff0c;生于淮北则为枳&#xff0c;叶徒相似&#xff0c;其实味不同。所以然者何&#xff1f;水土异也。今民生长于齐不盗&#xff0c;入楚则盗&#xff0c;得无楚之水土使民善盗耶&#xff1f;” 这段话的大意是说&#xff0c;橘树生长在淮河以南就是甜美…

python为什么慢?(自用)

《Cython系列》1. Cython 是什么&#xff1f;为什么要有 Cython&#xff1f;为什么我们要用 Cython&#xff1f; - 古明地盆 - 博客园 (cnblogs.com) 古明地盆的主页 - 博客园 (cnblogs.com) 我原本认为&#xff0c;python慢的原因是“逐行解释程序并执行”&#xff0c;那么我…

【ELK】filebeat 和logstash区别

Filebeat 和 Logstash 都是 Elastic Stack (也称为 ELK Stack) 的重要组件&#xff0c;用于日志数据的收集、处理和传输。它们有不同的功能和使用场景&#xff1a; Filebeat 角色: 轻量级日志收集器。功能: 从指定的日志文件中读取日志数据。可以从多个源&#xff08;如文件、…

记录自己Ubuntu加Nvidia驱动从入门到入土的一天

前言 记录一下自己这波澜壮阔的一天&#xff0c;遇到了很多问题&#xff0c;解决了很多问题&#xff0c;但是还有很多问题&#xff0c;终于在晚上的零点彻底放弃&#xff0c;重启windows。 安装乌班图 1.安装虚拟机 我开始什么操作系统的基础都没有&#xff0c;网上随便搜了…

SpringMVC简介

1、SpringMVC简介 1.1什么是MVC &#xff08;1&#xff09;MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分 M:Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据 JavaBean分为两类&#xff1a; 一类称为实体类Bea…