Java中的设计模式实战:单例、工厂、策略模式的最佳实践
Java中的设计模式实战:单例、工厂、策略模式的最佳实践
在Java开发中,设计模式是构建高效、可维护、可扩展应用程序的关键。本文将深入探讨三种常见且实用的设计模式:单例模式、工厂模式和策略模式,并通过详细代码实例,展示它们的最佳实践。
单例模式:确保全局唯一性
单例模式是最简单的创建型模式之一,它确保一个类只有一个实例,并提供一个全局访问点。单例模式有多种实现方式,但每种方式都有其适用场景和注意事项。
懒汉式单例
懒汉式单例在类被加载时不会立即实例化,而是在第一次调用getInstance()方法时才创建实例,这样可以延迟初始化,节省资源。
public class Singleton {private static Singleton instance;private Singleton() {}public static synchronized Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}
优点: 实现简单,按需初始化。
缺点: 每次调用getInstance()都需要进行同步,可能导致性能问题。
饿汉式单例
饿汉式单例在类加载时就立即实例化,确保了线程安全,但无法延迟初始化。
public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}
优点: 简单且线程安全。
缺点: 无法延迟初始化,可能导致资源浪费。
双重检查锁定(DCL)单例
DCL单例结合了懒汉式和饿汉式的优点,既实现了延迟初始化,又保证了线程安全。
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;}
}
优点: 实现了延迟初始化,且线程安全。
缺点: 代码相对复杂,需要理解volatile
的语义。
最佳实践: 在大多数场景下,推荐使用DCL单例,因为它兼顾了性能和线程安全。
工厂模式:创建对象的抽象
工厂模式是一种创建型模式,它提供一个创建对象的接口,但让子类决定实例化哪个类。工厂模式分为简单工厂模式、工厂方法模式和抽象工厂模式。
简单工厂模式
简单工厂模式定义一个创建对象的类,由这个类来封装实例化的过程。
public class SocialMediaFactory {public static SocialMedia getService(String type) {if ("facebook".equals(type)) {return new FacebookService();} else if ("twitter".equals(type)) {return new TwitterService();} else {throw new IllegalArgumentException("Unknown type: " + type);}}
}interface SocialMedia {void connect();
}class FacebookService implements SocialMedia {public void connect() {System.out.println("Connecting to Facebook");}
}class TwitterService implements SocialMedia {public void connect() {System.out.println("Connecting to Twitter");}
}
优点: 将对象的创建逻辑集中在一个类中,便于维护。
缺点: 违反开闭原则,添加新类型需要修改工厂类。
工厂方法模式
工厂方法模式定义一个创建对象的接口,但让子类决定实例化哪个类。
abstract class SocialMediaFactory {abstract SocialMedia createService();
}class FacebookFactory extends SocialMediaFactory {@OverrideSocialMedia createService() {return new FacebookService();}
}class TwitterFactory extends SocialMediaFactory {@OverrideSocialMedia createService() {return new TwitterService();}
}
优点: 符合开闭原则,添加新类型只需添加新工厂类。
缺点: 需要为每个产品类型创建一个工厂类。
抽象工厂模式
抽象工厂模式提供一个创建一系列相关或依赖对象的接口,而不需要指定它们具体的类。
interface PaymentFactory {Payment createPayment();
}class CreditCardFactory implements PaymentFactory {@Overridepublic Payment createPayment() {return new CreditCardPayment();}
}class PayPalFactory implements PaymentFactory {@Overridepublic Payment createPayment() {return new PayPalPayment();}
}abstract class Payment {abstract void processPayment(double amount);
}class CreditCardPayment extends Payment {@Overridevoid processPayment(double amount) {System.out.println("Processing credit card payment of $" + amount);}
}class PayPalPayment extends Payment {@Overridevoid processPayment(double amount) {System.out.println("Processing PayPal payment of $" + amount);}
}
优点: 可以创建一系列相关对象,而无需指定具体类。
缺点: 系统中类的数量会显著增加。
最佳实践: 根据需求选择合适的工厂模式。如果对象创建逻辑简单,使用简单工厂;如果需要扩展性,使用工厂方法;如果需要创建一系列相关对象,使用抽象工厂。
策略模式:算法的灵活切换
策略模式是一种行为型模式,它定义一系列算法,把它们一个个封装起来,并使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。
定义支付策略接口
public interface PaymentStrategy {void pay(double amount);
}
实现具体支付策略
public class CreditCardPayment implements PaymentStrategy {private String cardNumber;public CreditCardPayment(String cardNumber) {this.cardNumber = cardNumber;}@Overridepublic void pay(double amount) {System.out.println(amount + " paid with credit card " + cardNumber);}
}public class PayPalPayment implements PaymentStrategy {private String email;public PayPalPayment(String email) {this.email = email;}@Overridepublic void pay(double amount) {System.out.println(amount + " paid using PayPal " + email);}
}
使用策略上下文
public class ShoppingCart {private List<Item> items;private PaymentStrategy paymentStrategy;public ShoppingCart() {items = new ArrayList<>();}public void addItem(Item item) {items.add(item);}public void setPaymentStrategy(PaymentStrategy paymentStrategy) {this.paymentStrategy = paymentStrategy;}public void checkout() {double total = calculateTotal();paymentStrategy.pay(total);items.clear();System.out.println("Order processed successfully!");}private double calculateTotal() {double total = 0;for (Item item : items) {total += item.getPrice() * item.getQuantity();}return total;}
}class Item {private String name;private double price;private int quantity;public Item(String name, double price, int quantity) {this.name = name;this.price = price;this.quantity = quantity;}public String getName() {return name;}public double getPrice() {return price;}public int getQuantity() {return quantity;}
}
客户端代码
public class Main {public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();cart.addItem(new Item("Book", 20, 1));cart.addItem(new Item("Laptop", 999, 1));// 使用信用卡支付cart.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456"));cart.checkout();// 切换到PayPal支付cart.setPaymentStrategy(new PayPalPayment("user@example.com"));cart.addItem(new Item("Mouse", 19.99, 1));cart.checkout();}
}
优点: 策略模式使算法可以独立于使用它的客户端而变化,提供了灵活的算法切换能力。
缺点: 需要为每个具体策略实现一个类,可能导致类数量增加。
最佳实践: 在需要动态切换算法或策略的场景中,优先考虑使用策略模式。例如支付方式选择、算法优化等场景。
总结
单例模式、工厂模式和策略模式是Java开发中非常实用的设计模式。单例模式确保全局唯一性,工厂模式抽象对象创建过程,策略模式提供算法的灵活切换能力。在实际项目中,合理运用这些设计模式,可以显著提高代码的可维护性和可扩展性。
记住,设计模式不是万能的,它们应该根据具体需求谨慎选择和使用。过度使用设计模式可能导致系统复杂度增加,反而降低开发效率。理解每种模式的适用场景,并在实际项目中根据需求灵活运用,是成为优秀Java开发者的必经之路。
相关文章:

Java中的设计模式实战:单例、工厂、策略模式的最佳实践
Java中的设计模式实战:单例、工厂、策略模式的最佳实践 在Java开发中,设计模式是构建高效、可维护、可扩展应用程序的关键。本文将深入探讨三种常见且实用的设计模式:单例模式、工厂模式和策略模式,并通过详细代码实例࿰…...
DexGarmentLab 论文翻译
单个 专家 演示 装扮 15 任务 场景 2500+ 服装 手套 棒球帽 裤子 围巾 碗 帽子 上衣 外套 服装-手部交互 捕捉 摇篮 夹紧 平滑 任务 ...... 投掷 悬挂 折叠 ... 多样化位置 ... 多样化 变形 ... 多样化服装形状 类别级 一般化 类别级(有或没有变形) 服装具有相同结构 变形 生…...
Elasticsearch性能优化全解析
Elasticsearch作为一款分布式搜索和分析引擎,其性能优化是实际生产环境中必须深入研究的课题。本文基于Elastic官方文档,系统性地总结了从硬件配置、索引设计到查询优化的全链路优化策略,帮助用户构建高性能、高稳定性的集群。 Elasticsearch的优化需结合业务场景综合决策:…...

2025.05.28【Parallel】Parallel绘图:拟时序分析专用图
Improve general appearance Add title, use a theme, change color palette, control variable orders and more Highlight a group Highlight a group of interest to help people understand your story 文章目录 Improve general appearanceHighlight a group探索Paralle…...
tc3975开发板上有ft2232这块的电路,我想知道这个开发板有哪些升级方式,重点关注是怎样通过ft2232实现的烧录升级的
关于TC3975开发板上FT2232芯片支持的升级方式,特别是如何通过FT2232实现烧录升级的问题。首先,我得回忆一下FT2232的基本功能和常见应用场景。 FT2232是FTDI公司的一款双通道USB转UART/FIFO芯片,常用于嵌入式系统的调试和编程。它支持多种协议…...

自动驾驶与智能交通:构建未来出行的智能引擎
随着人工智能、物联网、5G和大数据等前沿技术的发展,自动驾驶汽车和智能交通系统正以前所未有的速度改变人类的出行方式。这一变革不仅是技术的融合创新,更是推动城市可持续发展的关键支撑。 一、自动驾驶与智能交通的定义 1. 自动驾驶(Auto…...
Kotlin Multiplatform与Flutter深度对比:跨平台开发方案的实战选择
简介 在当今多平台应用开发的浪潮中,Kotlin Multiplatform与Flutter代表了两种截然不同的技术路线。KMP以"共享代码、保留原生"为核心理念,允许开发者在业务逻辑层实现高达80%的跨平台代码共享,而Flutter则采用统一渲染引擎,在UI层提供100%的代码共享率。这两种…...

ELectron 中 BrowserView 如何进行实时定位和尺寸调整
背景 BrowserView 是继 Webview 后推出来的高性能多视图管理工具,与 Webview 最大的区别是,Webview 是一个 DOM 节点,依附于主渲染进程的附属进程,Webview 节点的崩溃会导致主渲染进程的连锁反应,会引起软件的崩溃。 …...

深兰科技董事长陈海波率队考察南京,加速AI大模型区域落地应用
近日,深兰科技创始人、董事长陈海波受邀率队赴南京市,先后考察了南京高新技术产业开发区与鼓楼区,就推进深兰AI医诊大模型在南京的落地应用,与当地政府及相关部门进行了深入交流与合作探讨。 此次考察聚焦于深兰科技自主研发的AI医…...

《深度关系-从建立关系到彼此信任》
陈海贤老师推荐的书,花了几个小时,感觉现在的人与人之间特别缺乏这种深度的关系,但是与一个人建立深度的关系并没有那么简单,反正至今为止,自己好像没有与任何一个人建立了这种深度的关系,那种双方高度同频…...

IT选型指南:电信行业需要怎样的服务器?
从第一条电报发出的 那一刻起 电信技术便踏上了飞速发展的征程 百余年间 将世界编织成一个紧密相连的整体 而在今年 我们迎来了第25届世界电信日 同时也是国际电联成立的第160周年 本届世界电信日的主题为:“弥合性别数字鸿沟,为所有人创造机遇”,但在新兴技术浪潮汹涌…...

【ConvLSTM第二期】模拟视频帧的时序建模(Python代码实现)
目录 1 准备工作:python库包安装1.1 安装必要库 案例说明:模拟视频帧的时序建模ConvLSTM概述损失函数说明(python全代码) 参考 ConvLSTM的原理说明可参见另一博客-【ConvLSTM第一期】ConvLSTM原理。 1 准备工作:pytho…...
[VMM]分享一个用SystemC编写的页表管理程序
分享一个用SystemC编写的页表管理程序 摘要:分享一个用SystemC编写的页表管理的程序,这个程序将模拟页表(PDE和PTE)的创建、虚拟地址(VA)到物理地址(PA)的转换,以及对内存的读写操作。 为了简化实现,我们做出以下假设: 页表是两级结构:PDE (Page Directory…...
将docker数据目录迁移到 home目录下
将 Docker 数据目录从默认位置(通常是 /var/lib/docker)迁移到 /home 目录下,可以通过几个步骤来完成。以下是详细的迁移步骤: 步骤 1:停止 Docker 服务 在进行任何操作之前,确保先停止 Docker 服务以避免…...

【论文解读】DETR: 用Transformer实现真正的End2End目标检测
1st authors: About me - Nicolas CarionFrancisco Massa - Google Scholar paper: [2005.12872] End-to-End Object Detection with Transformers ECCV 2020 code: facebookresearch/detr: End-to-End Object Detection with Transformers 1. 背景 目标检测&#…...
Pytest 是什么
Pytest 是 Python 生态中最流行的 测试框架,用于编写、运行和组织单元测试、功能测试甚至复杂的集成测试。它以简洁的语法、强大的插件系统和高度可扩展性著称,广泛应用于 Python 项目的自动化测试中。以下是其核心特性和使用详解: Pytest 的…...

ElasticSearch简介及常用操作指南
一. ElasticSearch简介 ElasticSearch 是一个基于 Lucene 构建的开源、分布式、RESTful 风格的搜索和分析引擎。 1. 核心功能 强大的搜索能力 它能够提供全文检索功能。例如,在海量的文档数据中,可以快速准确地查找到包含特定关键词的文档。这在处理诸如…...
缓存常见问题:缓存穿透、缓存雪崩以及缓存击穿
缓存常见问题 一、缓存穿透 (Cache Penetration) 是什么 缓存穿透是指客户端持续请求一个缓存和数据库中都根本不存在的数据。这导致每次请求都会先查缓存(未命中),然后穿透到数据库查询(也未命中)。如果这类请求量…...

纤维组织效应偏斜如何影响您的高速设计
随着比特率继续飙升,光纤编织效应 (FWE) 偏移,也称为玻璃编织偏移 (GWS),正变得越来越成为一个问题。今天的 56GB/s 是高速路由器中最先进的,而 112 GB/s 指日可待。而用于个人计算机…...
【深度学习】sglang 的部署参数详解
SGLang 的部署参数详解 SGLang(Structured Generation Language)是一个高性能的大语言模型推理框架,专为结构化生成和多模态应用设计。本文将全面介绍SGLang的部署参数,帮助你充分发挥其性能潜力。 🚀 SGLang 项目概览 SGLang是由UC Berkeley开发的新一代LLM推理引擎,…...
SDL2常用函数:SDL_RendererSDL_CreateRendererSDL_RenderCopySDL_RenderPresent
SDL 渲染器系统详解 SDL_Renderer 概述 SDL_Renderer 是 SDL 2.0 引入的核心渲染抽象,它提供了一种高效的、硬件加速的 2D 渲染方式,比传统的表面(Surface)操作更加高效和灵活。 主要函数 1. SDL_CreateRenderer - 创建渲染器 SDL_Renderer* SDL_Cr…...
[git]忽略.gitignore文件
git rm --cached .gitignore 是一个 Git 命令,主要用于 从版本控制中移除已追踪的 .gitignore 文件,但保留该文件在本地工作目录中。以下是详细解析: 一、命令拆解与核心作用 语法解析 git rm:Git 的删除命令,用于从版本库(Repository)中移除文件。--cached:关键参数…...
FEMFAT许可的有效期限
在工程仿真领域,FEMFAT作为一款领先的疲劳分析软件,为用户提供了强大的功能和卓越的性能。然而,为了确保软件的合法使用和持续合规,了解FEMFAT许可的有效期限至关重要。本文将为您详细解读FEMFAT许可的有效期限,帮助您…...

Rust使用Cargo构建项目
文章目录 你好,Cargo!验证Cargo安装使用Cargo创建项目新建项目配置文件解析默认代码结构 Cargo工作流常用命令速查表详细使用说明1. 编译项目2. 运行程序3.快速检查4. 发布版本构建 Cargo的设计哲学约定优于配置工程化优势 开发建议1. 新项目初始化2. …...

Python训练营打卡Day39
DAY 39 图像数据与显存 知识点回顾 1.图像数据的格式:灰度和彩色数据 2.模型的定义 3.显存占用的4种地方 a.模型参数梯度参数 b.优化器参数 c.数据批量所占显存 d.神经元输出中间状态 4.batchisize和训练的关系 作业:今日代码较少,理解内容…...

UE5蓝图中播放背景音乐和使用代码播放声音
UE5蓝图中播放背景音乐 1.创建背景音乐Cube 2.勾选looping 循环播放背景音乐 3.在关卡蓝图中 Event BeginPlay-PlaySound2D Sound选择自己创建的Bgm_Cube 蓝图播放声音方法二: 使用代码播放声音方法一 .h文件中 头文件引用 #include "Kismet/GameplayS…...

AI 赋能数据可视化:漏斗图制作的创新攻略
在数据可视化的广阔天地里,漏斗图以其独特的形状和强大的功能,成为展示流程转化、分析数据变化的得力助手。传统绘制漏斗图的方式往往需要耗费大量时间和精力,对使用者的绘图技能和软件操作熟练度要求颇高。但随着技术的蓬勃发展,…...

用 Python 模拟下雨效果
用 Python 模拟下雨效果 雨天别有一番浪漫情怀:淅淅沥沥的雨滴、湿润的空气、朦胧的光影……在屏幕上也能感受下雨的美妙。本文将带你用一份简单的 Python 脚本,手把手实现「下雨效果」动画。文章深入浅出,零基础也能快速上手,完…...

C#对象集合去重的一种方式
前言 现在AI越来越强大了,有很多问题其实不需要在去各个网站上查了,直接问AI就好了,但是呢,AI给的代码可能能用,也可能需要调整,但是自己肯定是要会的,所以还是总结一下吧。 问题 如果有一个…...
【LangChain】
以下是关于 LangChain框架 各核心组件的详细解析,结合其功能定位、技术实现和实际应用场景: 一、LangChain Libraries(核心库) 功能定位 跨语言支持:提供Python/JS双版本API,统一不同语言的LLM开发生态 …...