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

ops/2024/9/24 8:23:41/

创建型模式

单例模式(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/ops/56942.html

相关文章

CentOS6用文件配置IP模板

CentOS6用文件配置IP模板 到 CentOS6.9 , 默认还不能用 systemctl , 能用 service chkconfig sshd on 对应 systemctl enable sshd 启用,开机启动该服务 ### chkconfig sshd on 对应 systemctl enable sshd 启用,开机启动该服务 sudo chkconfig sshd onservice sshd start …

docker-compose mongodb 副本集

准备 cd /opt/mongos 把 3 个节点的数据目录创建好 mkdir -p ./mongos/{mongo1,mongo2,mongo3} mongodb 使用 keyFile 进行认证,副本集群中的每个节点的 mongodb 使用 keyFile 的内容作为认证其他成员的共享密码。mongodb 实例只有拥有正确的 keyFile 才可以加入副…

什么是RPC?有哪些RPC框架?

定义 RPC(Remote Procedure Call,远程过程调用)是一种允许运行在一台计算机上的程序调用另一台计算机上子程序的技术。这种技术屏蔽了底层的网络通信细节,使得程序间的远程通信如同本地调用一样简单。RPC机制使得开发者能够构建分…

iOS 开发者的 Flutter 入门课

作为一名 iOS 开发者,入门 Flutter 需要了解一些新的工具和概念,但也能利用你已有的知识和技能。以下是一个详细的入门指南,帮助你快速上手 Flutter: 1. 环境设置 首先,你需要设置开发环境。 安装 Flutter SDK 前往…

【鸿蒙学习笔记】交互事件

官方文档:交互事件 目录标题 分类交互事件-触屏交互事件-手势事件单一手势 分类 交互事件-触屏 在组件上按下(Down) , 滑动(Move) , 抬起(up)时触发的回调事件。包括点击事件、触摸事件和拖拽事件 交互事件-手势事件 在手机上点击打开应用 , 长按后拖动应用 , 这…

软件架构之信息系统基础知识(1)

软件架构之信息系统基础知识(1) 第 14 章:信息系统基础知识14.1 信息系统概述14.1.1 信息系统的组成14.1.2 信息系统的生命周期14.1.3 信息系统建设的原则14.1.4 信息系统开发方法 14.2 信息系统工程14.2.1 信息系统工程的概念14.2.3 信息系统…

【开发日记】Vue2动态路由踩坑指南

前言 背景是对一个Vue2的老项目进行动态路由改造,原来是静态路由。 踩坑指南 1、component中的符号不能由服务端返回,因为很可能会识别成其他内容。 component () > import(/${route.component});**2、**子路由的path不能以/开头,根路…

【计算机毕业设计】基于Springboot的智能推荐卫生健康系统【源码+lw+部署文档】

包含论文源码的压缩包较大,请私信或者加我的绿色小软件获取 免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累成果,供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者或出版方,资料版权归原作者或出版方所有,…