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

创建型模式

1.单例模式:

是java中最简单模式之一

特点:单例类只能有一个实例

           单例类必须自己创建自己的唯一实例

           单例类必须给所有其他对象提供这一实例

(1)饿汉式(比较常用,但容易产生垃圾对象):

优点:没有加锁,执行效率会提高,线程安全,获取实例速度快(提前创建好了,类加载时就创建实例)

缺点:类加载时就初始化,不能延迟加载,浪费内存

适用于:单例对象较小,对内存要求不高的场景

//静态代码块:只执行一次
//线程安全  浪费资源
public class Eager1 {private Eager1(){ }private static Eager1 instance;//实例public static Eager1 getInstance() {//访问点,只能通过getInstance这个方法访问return instance;}//利用静态代码块的特点来完成单例的创建static{instance=new Eager1();}
}
//常量
public class Eager2 {private static final Eager2 instance=new Eager2();//finalprivate Eager2(){}public static Eager2 getInstance()//访问点{return instance;}
}

(2)懒汉式:

是一种延迟初始化的实现方式,只有在第一次使用时才会创建实例。

基础懒汉式:

优点:延迟初始化,第一次调用的时候才创建实例,避免了不必要的资源占用,灵活控制初始化时机,可以在运行时决定是否初始化

缺点:在多线程环境下可能创建多个实例,破坏单例原则

适用场景:适合初始化成本高的对象(数据库连接池、线程池等)

非线程安全:

public class Singleton {private static Singleton instance;private Singleton() {}  // 私有构造public static Singleton getInstance() {if (instance == null) {          // 第一次调用时创建instance = new Singleton();  // 非线程安全!}return instance;}
}

线程安全改进,加锁:

public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {//synchronized 加锁if (instance == null) {instance = new Singleton();}return instance;}
}

(3)双重检查锁

        结合延迟加载和线程安全,减少同步锁的开销

public class Singleton {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;}
}

volaile 关键字禁止指令重排序,避免返回未初始化的实例。两次检查确保线程安全。

优点:线程安全且性能较高

缺点:代码较复杂,需理解内存模型

适合场景:高并发环境

(4)静态内部类

        利用类加载机制保证线程安全,同时延迟加载

public class Singleton {private Singleton() {}private static class Holder {private static final Singleton instance = new Singleton();}public static Singleton getInstance() {return Holder.instance;}
}

原理:内部类holder在getinstance()首次调用时才会加载

优点:线程安全、延迟加载、无锁高性能

缺点:无法防止反射攻击

适用场景:大多数场景

(5)枚举

基于枚举类型的天然单例特性,防止反射和序列化破坏

public enum Singleton {INSTANCE;public void doSomething() {// 业务方法}
}

优点:线程安全,天然防止反射创建新实例,自动处理序列化和反序列化

缺点:不够灵活(无法继承其他类)

适用场景:需要绝对防止多实例的场景(如配置管理器)

2.原型模式

通过复制现有对象(原型)来创建新对象,而不是通过new关键字实例化。这种方式特别适用于创建成本较高的对象,或者当系统需要独立于对象创建和构成的方式时。

声明克隆方法的接口

实现克隆方法的具体类

通过复制原型来创建新对象

浅拷贝:

使用 Object.clone() 方法直接调用 super.clone(),依赖 JVM 的默认浅拷贝行为,复制字段值(包括引用地址)。
// 1. 原型接口
interface Prototype extends Cloneable {Prototype clone();
}// 2. 具体原型
class ConcretePrototype implements Prototype {private String field;private List<String> listField;public ConcretePrototype(String field, List<String> list) {this.field = field;this.listField = list;}// 浅拷贝实现public Prototype clone() {try {return (ConcretePrototype)super.clone();} catch (CloneNotSupportedException e) {return null;}}// getters and setters
}// 3. 客户端使用
public class Client {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("item1");ConcretePrototype original = new ConcretePrototype("value", list);ConcretePrototype copy = (ConcretePrototype)original.clone();System.out.println(original == copy);  // false - 不同对象System.out.println(original.getListField() == copy.getListField());  // true - 共享引用}
}

深拷贝:

手动创建新对象并复制数据显式通过 new 和构造函数创建新对象,并复制引用类型字段的实际内容。
class ConcretePrototype implements Prototype {private String field;private List<String> listField;public ConcretePrototype(String field, List<String> list) {this.field = field;this.listField = new ArrayList<>(list);  // 防御性复制}// 深拷贝实现public Prototype clone() {List<String> newList = new ArrayList<>(this.listField);return new ConcretePrototype(this.field, newList);}// getters and setters
}// 客户端使用
public class Client {public static void main(String[] args) {List<String> list = new ArrayList<>();list.add("item1");ConcretePrototype original = new ConcretePrototype("value", list);ConcretePrototype copy = (ConcretePrototype)original.clone();System.out.println(original == copy);  // falseSystem.out.println(original.getListField() == copy.getListField());  // false}
}

应用场景:对象创建成本高

优点:

性能优化:避免重复初始化操作

灵活性:动态添加和删除产品

简化创建结构:避免复杂的创建层次

保护性拷贝:可以方便地实现防御性编程

缺点:

深拷贝实现复杂:特别是对象包含循环引用时

需要克隆方法:每个类都需要正确实现克隆方法

可能违反封装:需要暴露对象内部细节来实现克隆

简单工厂:

角色:抽象产品(定义产品的接口或抽象类)、具体产品(实现抽象产品的具体类)、工厂类(根据参数创建并返回具体产品的实例)

代码示例:

// 1. 抽象产品:定义接口
interface Shape {void draw();
}// 2. 具体产品:实现接口
class Circle implements Shape {@Overridepublic void draw() {System.out.println("绘制圆形");}
}class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("绘制矩形");}
}// 3. 工厂类:根据参数创建对象
class ShapeFactory {public Shape createShape(String type) {if ("circle".equalsIgnoreCase(type)) {return new Circle();} else if ("rectangle".equalsIgnoreCase(type)) {return new Rectangle();}throw new IllegalArgumentException("未知图形类型: " + type);}
}// 4. 客户端使用
public class Client {public static void main(String[] args) {ShapeFactory factory = new ShapeFactory();Shape shape = factory.createShape("circle");shape.draw(); // 输出:绘制圆形}
}
 缺点与局限
  1. 违反开闭原则(OCP)
    新增产品类型(如 Triangle)需修改工厂类的 createShape() 方法。

  2. 工厂类职责过重
    所有产品的创建逻辑集中在一个类中,可能导致代码臃肿。

适用于产品类型固定、无需频繁扩展的场景。尽管其 违反开闭原则,但在小型项目或快速开发中仍具有实用价值。对于复杂系统,建议结合工厂方法或抽象工厂模式提升扩展性。

3.工厂方法:

核心思想是 将对象的创建延迟到子类。通过定义一个创建对象的接口,但让子类决定具体实例化哪个类,实现 对象创建与使用的解耦,符合开闭原则(对扩展开放,对修改关闭)。

角色:抽象产品(定义产品的接口或抽象类)、具体产品(实现抽象产品的具体类)、抽象工厂(声明工厂方法,返回抽象产品类型)、具体工厂(实现工厂方法,生成具体产品)

代码示例:

// 1. 抽象产品
interface Document {void open();void save();
}// 2. 具体产品
class WordDocument implements Document {@Overridepublic void open() { System.out.println("打开Word文档"); }@Overridepublic void save() { System.out.println("保存Word文档"); }
}class PDFDocument implements Document {@Overridepublic void open() { System.out.println("打开PDF文档"); }@Overridepublic void save() { System.out.println("保存PDF文档"); }
}// 3. 抽象工厂
interface DocumentFactory {Document createDocument();
}// 4. 具体工厂
class WordFactory implements DocumentFactory {@Overridepublic Document createDocument() {return new WordDocument();}
}class PDFFactory implements DocumentFactory {@Overridepublic Document createDocument() {return new PDFDocument();}
}// 5. 客户端使用
public class Client {public static void main(String[] args) {DocumentFactory factory = new WordFactory();Document doc = factory.createDocument();doc.open(); // 输出:打开Word文档}
}
核心优点
  1. 符合开闭原则
    新增产品类型时,只需添加对应的具体工厂和产品类,无需修改已有代码。

  2. 解耦客户端与具体类
    客户端仅依赖抽象接口(Document 和 DocumentFactory),不直接耦合具体实现。

  3. 支持多态性
    工厂方法可返回不同子类对象,实现灵活的对象创建逻辑。

缺点
  1. 类数量膨胀
    每个产品需对应一个工厂类,增加系统复杂度。

  2. 抽象性要求高
    需要预先设计抽象层,对简单场景可能过度设计。

适用场景
  • 对象类型不确定:需运行时动态决定创建哪种对象(如配置文件驱动)。

  • 扩展性强:预期系统需频繁新增产品类型(如插件系统)。

  • 框架设计:允许用户自定义组件(如Spring的BeanFactory)。

4.抽象工厂

模式定义

抽象工厂模式是一种创建型设计模式,提供 创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。其核心是 围绕产品族(一组有逻辑关联的产品)进行对象创建,确保同一族的产品能协同工作。

核心结构

抽象工厂模式包含以下角色:

  1. 抽象工厂(Abstract Factory)

    定义创建一系列产品对象的接口(如createButton()createCheckbox())。
  2. 具体工厂(Concrete Factory)

    实现抽象工厂接口,生产同一产品族的对象(如WindowsFactory生产Windows风格组件)。
  3. 抽象产品(Abstract Product)

    定义一类产品的接口(如ButtonCheckbox)。
  4. 具体产品(Concrete Product)

    实现抽象产品接口的具体类(如WindowsButtonMacCheckbox)。
代码示例
步骤1:定义抽象产品
// 按钮抽象接口
interface Button {void render();
}// 复选框抽象接口
interface Checkbox {void check();
}

步骤2:定义具体产品

// Windows风格按钮
class WindowsButton implements Button {@Overridepublic void render() {System.out.println("渲染一个Windows风格按钮");}
}// Mac风格按钮
class MacButton implements Button {@Overridepublic void render() {System.out.println("渲染一个Mac风格按钮");}
}// Windows风格复选框
class WindowsCheckbox implements Checkbox {@Overridepublic void check() {System.out.println("勾选Windows风格复选框");}
}// Mac风格复选框
class MacCheckbox implements Checkbox {@Overridepublic void check() {System.out.println("勾选Mac风格复选框");}
}

步骤3:定义抽象工厂

interface GUIFactory {Button createButton();Checkbox createCheckbox();
}

步骤4:实现具体工厂

// Windows工厂生产同一族产品
class WindowsFactory implements GUIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic Checkbox createCheckbox() {return new WindowsCheckbox();}
}// Mac工厂生产同一族产品
class MacFactory implements GUIFactory {@Overridepublic Button createButton() {return new MacButton();}@Overridepublic Checkbox createCheckbox() {return new MacCheckbox();}
}

步骤5:客户端使用

public class Application {private Button button;private Checkbox checkbox;public Application(GUIFactory factory) {button = factory.createButton();checkbox = factory.createCheckbox();}public void renderUI() {button.render();checkbox.check();}public static void main(String[] args) {// 根据配置选择工厂GUIFactory factory;String osType = System.getProperty("os.name").toLowerCase();if (osType.contains("windows")) {factory = new WindowsFactory();} else {factory = new MacFactory();}Application app = new Application(factory);app.renderUI();}
}
模式优势

强产品族一致性:确保同一工厂创建的对象兼容(如所有组件风格统一)。

客户端与具体类解耦:客户端仅依赖抽象接口,不关心具体实现。

易于切换产品族:通过替换工厂实例,可快速切换整套产品(如从Windows主题切换为Mac主题)。

模式缺点

新增产品困难:若需在已有产品族中增加新产品(如新增RadioButton),需修改所有工厂接口和实现类,违反开闭原则。

类数量膨胀:每新增一个产品族,需新增多个具体产品类和工厂类

适用场景
  1. 跨平台UI开发

    不同操作系统的按钮、菜单、对话框需要风格一致。
  2. 数据库兼容

    支持多种数据库(MySQL、Oracle),同一族产品包括Connection、Statement、ResultSet。
  3. 游戏引擎

    为不同画质等级(低、中、高)创建配套的模型、贴图、特效。
对比工厂方法模式
维度工厂方法模式抽象工厂模式
核心目标创建单一产品创建相关产品族
扩展方向新增产品类型(垂直扩展)新增产品族(水平扩展)
代码复杂度较低(一个工厂对应一个产品)较高(一个工厂对应多个产品)
典型场景支付方式(支付宝、微信)跨平台UI组件、数据库驱动兼容

总结

抽象工厂模式是 管理复杂对象创建 的利器,尤其适合需要保证多对象协同工作的场景。尽管存在扩展性限制,但在产品族明确且稳定的系统中,它能显著提升代码的可维护性和灵活性。

5.创建者模式

模式定义

建造者模式是一种 创建型设计模式,用于 分步骤构建复杂对象。它通过将对象的构造过程与表示分离,使得 相同的构建过程可以创建不同的对象形式
核心价值

简化多参数对象的创建(尤其当参数可选或存在依赖时)。

提高代码可读性(链式调用更直观)。

支持构造过程的精细化控制(如必填字段校验)。

核心结构

建造者模式通常包含以下角色:

  1. 产品(Product)

    最终要构建的复杂对象(如 Computer)。
  2. 抽象建造者(Builder)

    定义构造产品的通用步骤接口(如 setCPU()setRAM())。
  3. 具体建造者(Concrete Builder)

    实现抽象建造者接口,提供具体的构造逻辑。
  4. 指挥者(Director,可选)

    控制构造流程(如定义标准化的组装步骤)。
     

代码示例:自定义电脑配置

步骤1:定义产品类

public class Computer {private String cpu;      // 必填private String ram;      // 必填private String ssd;      // 可选private String gpu;      // 可选public Computer(String cpu, String ram, String ssd, String gpu) {this.cpu = cpu;this.ram = ram;this.ssd = ssd;this.gpu = gpu;}// 省略Getter方法...
}

步骤2:定义建造者接口

public interface ComputerBuilder {ComputerBuilder setCPU(String cpu);  // 必填ComputerBuilder setRAM(String ram);  // 必填ComputerBuilder setSSD(String ssd);  // 可选ComputerBuilder setGPU(String gpu);  // 可选Computer build();                   // 最终构建方法
}

步骤3:实现具体建造者

public class StandardComputerBuilder implements ComputerBuilder {private String cpu;private String ram;private String ssd;private String gpu;@Overridepublic ComputerBuilder setCPU(String cpu) {this.cpu = cpu;return this;}@Overridepublic ComputerBuilder setRAM(String ram) {this.ram = ram;return this;}@Overridepublic ComputerBuilder setSSD(String ssd) {this.ssd = ssd;return this;}@Overridepublic ComputerBuilder setGPU(String gpu) {this.gpu = gpu;return this;}@Overridepublic Computer build() {// 校验必填参数if (cpu == null || ram == null) {throw new IllegalArgumentException("CPU和RAM是必填参数");}return new Computer(cpu, ram, ssd, gpu);}
}

步骤4:客户端使用

public class Client {public static void main(String[] args) {Computer gamingPC = new StandardComputerBuilder().setCPU("Intel i9")    // 链式调用.setRAM("32GB").setGPU("RTX 4090").build();Computer officePC = new StandardComputerBuilder().setCPU("Intel i5").setRAM("8GB").setSSD("512GB").build();}
}
模式优势

参数灵活:可选参数无需传递null,避免构造方法爆炸。

代码可读性高:链式调用清晰表达参数含义(如 .setCPU("i7"))。

构造过程可控:支持参数校验、分步构建(如先设置必填项,再添加可选项)。

适用场景
  1. 复杂对象的创建

    对象包含多个部件(如订单包含商品、用户、地址等)。
  2. 参数存在依赖关系

    例如,选择“高性能模式”时自动启用特定配置。
  3. 不可变对象的构建

    通过建造者一次性设置所有参数,避免对象状态中途修改。

总结

建造者模式是处理 多参数对象创建 的最佳实践,尤其适合以下场景:

参数存在大量可选或依赖关系。

需要提高代码可读性和可维护性。

希望支持灵活的构造过程(如参数校验、分步构建)。

通过链式调用和分离构造逻辑,它能显著简化复杂对象的创建,是Java开发者工具箱中的必备设计模式。

http://www.xdnf.cn/news/6817.html

相关文章:

  • python 自动化教程
  • 布隆过滤器和布谷鸟过滤器
  • Python 在黎曼几何中的应用
  • OGGMA 21c 微服务 (MySQL) 安装避坑指南
  • .NET Core 中 Swagger 配置详解:常用配置与实战技巧
  • 技术测评:小型单文件加密工具的功能解析
  • 线性回归策略
  • Linux zip、unzip 压缩和解压
  • 冒泡排序-java
  • stack和queue简单模拟实现
  • 一个可拖拉实现列表排序的WPF开源控件
  • 使用lvm进行磁盘分区
  • LLVM编译器
  • 安装nerdctl和buildkitd脚本命令
  • Go语言深度解析:发展历程、应用场景与性能对比
  • 【springboot+vue3的前后端分离项目实现支付宝的沙箱支付】
  • 从零开始理解Jetty:轻量级Java服务器的入门指南
  • C++跨平台开发:挑战与应对策略
  • Linux:基础IO
  • EXO分布式部署deepseek r1
  • (面试)TCP、UDP协议
  • 38-日语学习小程序
  • 【滑动窗口】P4085 [USACO17DEC] Haybale Feast G|普及+
  • OpenCV透视变换
  • C++学习:六个月从基础到就业——C++11/14:decltype关键字
  • JavaScript进阶(十)
  • 3D个人简历网站 4.小岛
  • Python爬虫(29)Python爬虫高阶:动态页面处理与云原生部署全链路实践(Selenium、Scrapy、K8s)
  • Adobe Illustrator学习备忘
  • 【论文阅读】A Survey on Multimodal Large Language Models