【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库生成图像的文章是很多的,使用方法也并不复杂,安装库后调用现成的模型和接口即可,但是因为网络原因,模型下载总会遇到问题,对于使用服务器的研究者来说,挂梯子并不可行,…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
