【HeadFirst系列之HeadFirst设计模式】第14天之与设计模式相处:真实世界中的设计模式
与设计模式相处:真实世界中的设计模式
设计模式是软件开发中的经典解决方案,它们帮助我们解决常见的设计问题,并提高代码的可维护性和可扩展性。在《Head First设计模式》一书中,作者通过生动的案例和通俗的语言,深入浅出地介绍了各种设计模式的核心思想和使用场景。本文将基于书中的“与设计模式相处-真实世界中的模式”章节,提炼总结设计模式的核心内容,并结合实际应用场景和代码示例,帮助大家更好地理解和应用设计模式。
1. 设计模式的核心思想
1.1 遇到什么问题?
在软件开发过程中,我们经常会遇到一些重复出现的问题,例如:
- 代码重复:相似的代码在不同的地方重复出现,导致维护困难。
- 紧耦合:模块之间的依赖关系过于紧密,修改一个模块可能会影响其他模块。
- 扩展性差:系统难以扩展,新增功能时需要修改大量现有代码。
1.2 怎么解决的?
设计模式提供了一套经过验证的解决方案,帮助我们解决上述问题。它们通过封装变化、解耦依赖、提高复用性等方式,使代码更加灵活和可维护。
1.3 引入设计模式
设计模式并不是银弹,它们并不是用来解决所有问题的。相反,设计模式是用来解决特定场景下的特定问题的。在使用设计模式时,我们需要根据具体的问题场景选择合适的模式。
1.4 使用场景
设计模式的使用场景非常广泛,几乎涵盖了软件开发的各个方面。例如:
- 创建型模式:用于对象的创建,如工厂模式、单例模式等。
- 结构型模式:用于类和对象的组合,如适配器模式、装饰器模式等。
- 行为型模式:用于对象之间的交互,如观察者模式、策略模式等。
1.5 优缺点
设计模式的优点在于它们提供了一套经过验证的解决方案,可以帮助我们快速解决常见的设计问题。然而,设计模式也有其缺点,例如:
- 过度设计:在不必要的情况下使用设计模式,可能会导致代码复杂化。
- 学习曲线:设计模式需要一定的学习成本,初学者可能需要花费一些时间来理解和掌握。
2. 设计模式在JDK和Spring框架中的应用
2.1 JDK中的设计模式
JDK中广泛使用了各种设计模式,以下是一些常见的例子:
2.1.1 工厂模式
java.util.Calendar
类中的 getInstance()
方法就是一个典型的工厂方法模式的应用。它根据不同的时区和地区返回不同的 Calendar
实例。
Calendar calendar = Calendar.getInstance();
2.1.2 单例模式
java.lang.Runtime
类是一个典型的单例模式的应用。Runtime
类提供了访问运行时环境的方法,并且在整个应用程序中只有一个实例。
Runtime runtime = Runtime.getRuntime();
2.1.3 观察者模式
java.util.Observable
和 java.util.Observer
是观察者模式的实现。Observable
类代表被观察的对象,Observer
接口代表观察者。
class ConcreteObserver implements Observer {@Overridepublic void update(Observable o, Object arg) {System.out.println("Received update: " + arg);}
}Observable observable = new Observable();
observable.addObserver(new ConcreteObserver());
observable.notifyObservers("Hello, Observer!");
2.2 Spring框架中的设计模式
Spring框架中也大量使用了设计模式,以下是一些常见的例子:
2.2.1 依赖注入(DI)模式
Spring框架的核心就是依赖注入模式。通过依赖注入,Spring可以将对象的依赖关系从代码中解耦出来,使得代码更加灵活和可测试。
@Service
public class MyService {private final MyRepository repository;@Autowiredpublic MyService(MyRepository repository) {this.repository = repository;}
}
2.2.2 代理模式
Spring AOP(面向切面编程)使用了代理模式来实现横切关注点的分离。Spring通过动态代理为目标对象创建代理对象,从而在不修改原始代码的情况下增强其功能。
@Aspect
@Component
public class LoggingAspect {@Before("execution(* com.example.service.*.*(..))")public void logBefore(JoinPoint joinPoint) {System.out.println("Before method: " + joinPoint.getSignature().getName());}
}
2.2.3 模板方法模式
Spring的 JdbcTemplate
类是一个典型的模板方法模式的应用。JdbcTemplate
封装了JDBC操作的通用流程,用户只需要关注具体的SQL语句和结果处理。
@Autowired
private JdbcTemplate jdbcTemplate;public List<User> getAllUsers() {return jdbcTemplate.query("SELECT * FROM users", new BeanPropertyRowMapper<>(User.class));
}
3. 代码示例
3.1 策略模式
策略模式允许我们定义一系列算法,并将它们封装在独立的类中,使得它们可以互换使用。以下是一个简单的策略模式示例:
interface Strategy {int execute(int a, int b);
}class AddStrategy implements Strategy {@Overridepublic int execute(int a, int b) {return a + b;}
}class SubtractStrategy implements Strategy {@Overridepublic int execute(int a, int b) {return a - b;}
}class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public int executeStrategy(int a, int b) {return strategy.execute(a, b);}
}public class StrategyPatternDemo {public static void main(String[] args) {Context context = new Context(new AddStrategy());System.out.println("10 + 5 = " + context.executeStrategy(10, 5));context = new Context(new SubtractStrategy());System.out.println("10 - 5 = " + context.executeStrategy(10, 5));}
}
3.2 装饰器模式
装饰器模式允许我们动态地为对象添加新的行为,而不会影响其他对象。以下是一个简单的装饰器模式示例:
interface Coffee {String getDescription();double getCost();
}class SimpleCoffee implements Coffee {@Overridepublic String getDescription() {return "Simple Coffee";}@Overridepublic double getCost() {return 5.0;}
}class MilkDecorator implements Coffee {private Coffee coffee;public MilkDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic String getDescription() {return coffee.getDescription() + ", Milk";}@Overridepublic double getCost() {return coffee.getCost() + 1.5;}
}public class DecoratorPatternDemo {public static void main(String[] args) {Coffee coffee = new SimpleCoffee();System.out.println(coffee.getDescription() + " $" + coffee.getCost());coffee = new MilkDecorator(coffee);System.out.println(coffee.getDescription() + " $" + coffee.getCost());}
}
4. 总结
设计模式是软件开发中的宝贵财富,它们帮助我们解决常见的设计问题,并提高代码的可维护性和可扩展性。通过理解设计模式的核心思想和使用场景,我们可以更好地应用它们来解决实际问题。同时,JDK和Spring框架中的设计模式应用也为我们提供了丰富的参考案例。希望本文能够帮助大家更好地理解和应用设计模式,写出更加优雅和高效的代码。
参考文献:
- 《Head First设计模式》 by Eric Freeman, Elisabeth Robson, Bert Bates, Kathy Sierra
相关文章:

【HeadFirst系列之HeadFirst设计模式】第14天之与设计模式相处:真实世界中的设计模式
与设计模式相处:真实世界中的设计模式 设计模式是软件开发中的经典解决方案,它们帮助我们解决常见的设计问题,并提高代码的可维护性和可扩展性。在《Head First设计模式》一书中,作者通过生动的案例和通俗的语言,深入…...
JDBC 完全指南:掌握 Java 数据库交互的核心技术
JDBC 完全指南:掌握 Java 数据库交互的核心技术 一、JDBC 是什么?为什么它如此重要? JDBC(Java Database Connectivity)是 Java 语言中用于连接和操作关系型数据库的标准 API。它允许开发者通过统一的接口访问不同的数…...
Vue父子组件传递笔记
Vue父子组件传递笔记 props 父组件向子组件进行传值 (1)在父组件APP.vue <template><div> <!-- 给子组件Child.vue传递以msg的信号,传递的信息内容为messages --><Child :msg"messages"></Child>…...

文件上传漏洞与phpcms漏洞安全分析
目录 1. 文件上传漏洞简介 2. 文件上传漏洞的危害 3. 文件上传漏洞的触发条件 1. 文件必须能被服务器解析执行 2. 上传目录必须支持代码执行 3. 需要能访问上传的文件 4. 例外情况:非脚本文件也可能被执行 4. 常见的攻击手法 4.1 直接上传恶意文件 4.2 文件…...
【deepseek】辅助思考生物学问题:ICImapping构建遗传图谱gap较大
基于ICImapping构建遗传图谱的常见问题与解答 问题一:染色体两端标记间遗传距离gap较大 答疑一 标记密度不足(如芯片设计时分布不均)重组概率低基因组结构变异软件算法限制 Deepseek的解释 #### 1. **染色体末端的重组率较低** - **现象*…...

linux磁盘非lvm分区
linux磁盘非lvm分区 类似于windows划分C盘、D盘,并且不需要多个磁盘空间合一 图形化直接分区 通过gparted 这个提供直观的图形化分区,类似windows的磁盘管理工具 下载方式: 乌班图/debian系列: sudo apt install gparted红帽…...
Windows下sql server2012安装流程
准备工作 确认系统要求:确保 Windows 系统为 Windows 7 或更高版本,且为 64 位操作系统,CPU 在 2GHz 以上,内存 4GB 或更高。 下载安装包:从微软官方网站或其他可靠渠道下载 SQL Server 2012 安装包。 关闭相关软件&am…...
css之英文换行样式
在 CSS 中,要实现英文文本自动换行但不从单词中间断开的效果,可以使用 word-wrap 或 overflow-wrap 属性。以下是相关的 CSS 属性和它们的配置: 使用 overflow-wrap 或 word-wrap /* This property is used to handle word breaking */ .wo…...

绝美焦糖暖色调复古风景画面Lr调色教程,手机滤镜PS+Lightroom预设下载!
调色教程 通过 Lr 软件丰富的工具和功能,对风景照片在色彩、影调等方面进行调整。例如利用基本参数调整选项,精准控制照片亮度、对比度、色温、色调等基础要素;运用 HSL 面板可对不同色彩的色相、饱和度以及明亮度进行单独调节;利…...
文件解析:doc、docx、pdf
1.doc解析 ubuntu/debian系统应先安装工具 apt-get install python-dev libxml2-dev libxslt1-dev antiword unrtf poppler-utils pstotext tesseract-ocr \ flac ffmpeg lame libmad0 libsox-fmt-mp3 sox libjpeg-dev swig pip install textract解析: import te…...

计算机网络基础:VLAN(虚拟局域网)
1. VLAN 虚拟局域网:可以用来隔离广播 广播和广播域: arp 出不了路由器,只能攻击内网 路由器可以隔离广播(物理隔离)缺点是成本高、不灵活 2. VLAN 隔离广播 静态VLAN:基于交换机端口号划分 动态VLAN&am…...
C++学习笔记(十一)——循环结构
循环结构的作用 循环结构用于重复执行某一代码块,直到满足特定条件后退出循环。 C 提供了以下三种循环结构: for 循环(确定次数的循环)while 循环(条件控制的循环)do-while 循环(至少执行一次的…...

【C++】二叉树相关算法题
一、根据二叉树创建字符串 题目描述: 给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。 空节点使用一对空括号对 “()” 表示,转化后需要省略所有…...

物联网IoT系列之MQTT协议基础知识
文章目录 物联网IoT系列之MQTT协议基础知识物联网IoT是什么?什么是MQTT?为什么说MQTT是适用于物联网的协议?MQTT工作原理核心组件核心机制 MQTT工作流程1. 建立连接2. 发布和订阅3. 消息确认4. 断开连接 MQTT工作流程图MQTT在物联网中的应用 …...

【大学生体质】智能 AI 旅游推荐平台(Vue+SpringBoot3)-完整部署教程
智能 AI 旅游推荐平台开源文档 项目前端地址 ☀️项目介绍 智能 AI 旅游推荐平台(Intelligent AI Travel Recommendation Platform)是一个利用 AI 模型和数据分析为用户提供个性化旅游路线推荐、景点评分、旅游攻略分享等功能的综合性系统。该系统融合…...
【Node.js入门笔记1---初始Node.js)】
Node.js入门笔记1 初始Node.js1.Node.js简介2.Node.js中js的运行环境3.Node.js 可以做什么4.Node.js 怎么学 初始Node.js 1.Node.js简介 Node.js 是一个基于 Chrome V8 引擎 的 JavaScript 运行时环境,用于在服务器端运行 JavaScript 代码。它让开发者可以用 Java…...

自学Java-JavaSE基础加强(多线程)
自学Java-JavaSE基础加强(多线程) 一、创建线程1、方式一:继承Thread类小结 2、方式二:实现Runnable接口小结 3、方式三:实现Callable接口4、小结 二、线程的常用方法三、线程安全1、认识线程安全2、模拟线程安全问题3…...

数字后端培训实战项目六大典型后端实现案例
Q1:请教一个问题,cts.sdc和func.sdc在innovus用如何切换?在flow哪一步切换输入cts.sdc?哪一步切换到func.sdc,具体如何操作? 这个学员其实就是在问使用分段长clock tree时具体的flow流程是怎么样的?针对时…...

安卓免费多功能工具:一站式解决 PDF 阅读、编辑、转换等需求
软件介绍 今天要给大家介绍一款功能强大的PDF处理软件——PDFgear Android版。它是专为安卓设备打造的,完全免费,无需破解和激活就能使用。 此前,我们分享过它的桌面端,收获了大家的一致好评。今天要着重介绍的手机APP版本&…...

diffuser库使用本地模型生成图像
实验目的 使用diffuser库生成图像的文章是很多的,使用方法也并不复杂,安装库后调用现成的模型和接口即可,但是因为网络原因,模型下载总会遇到问题,对于使用服务器的研究者来说,挂梯子并不可行,…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...