当前位置: 首页 > news >正文

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

创建型模式

单例模式(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 方法克隆这些对象,并使用克隆的对象。

总结

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Mojo 编程语言:AI开发者的新宠儿
  • SQLite3封装类教程
  • Linux 复现Docker NAT网络
  • 如何在 CentOS 上配置本地 YUM 源
  • 2024软件测试面试题汇总【备战金九银十】内容较长建议收藏
  • mybatilsplaus 常用注解
  • 本地部署,去除动漫图像背景Anime Remove Background
  • Blinn-Phong优化phong模型的数学依据
  • 前端的页面代码
  • 代码随想录算法训练营:26/60
  • 通义千问Qwen-VL-Chat大模型本地训练(二)
  • Spring Boot 实现统一异常处理:构建健壮的应用
  • 恢复出厂设置手机变成砖
  • 网关、DHCP协议、ip地址、子网掩码简单介绍
  • 【AutoencoderKL】基于stable-diffusion-v1.4的vae对图像重构
  • 11111111
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • HTTP--网络协议分层,http历史(二)
  • js对象的深浅拷贝
  • js中forEach回调同异步问题
  • Python - 闭包Closure
  • React的组件模式
  • spring boot下thymeleaf全局静态变量配置
  • Spring Cloud Feign的两种使用姿势
  • Webpack 4x 之路 ( 四 )
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 代理模式
  • 和 || 运算
  • 如何设计一个微型分布式架构?
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 小程序01:wepy框架整合iview webapp UI
  • 用element的upload组件实现多图片上传和压缩
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 责任链模式的两种实现
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • hi-nginx-1.3.4编译安装
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​业务双活的数据切换思路设计(下)
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #Java第九次作业--输入输出流和文件操作
  • #在 README.md 中生成项目目录结构
  • $.ajax()参数及用法
  • (31)对象的克隆
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (八)Flask之app.route装饰器函数的参数
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (二开)Flink 修改源码拓展 SQL 语法
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (接口自动化)Python3操作MySQL数据库
  • (未解决)macOS matplotlib 中文是方框
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]