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

深入理解常见的设计模式

目录

引言

1. 单例模式(Singleton Pattern)

应用场景:

示例代码:

. 工厂模式(Factory Pattern)

应用场景:

示例代码:

3. 观察者模式(Observer Pattern)

应用场景:

示例代码:

4. 策略模式(Strategy Pattern)

应用场景:

示例代码:

5、装饰器模式(Decorator Pattern)

核心概念

应用场景

在项目中的应用示例

Component:File

ConcreteComponent:FileStream

Decorator:FileDecorator

ConcreteDecorator:BufferedFile

使用示例

总结


引言

设计模式是软件开发中常用的解决方案,它们提供了一套经过验证的解决问题的模板。在本文中,我们将深入探讨几种常见的设计模式,并展示它们在实际项目中的应用。

1. 单例模式(Singleton Pattern)

单例模式用于确保一个类只有一个实例,并提供一个全局访问点。在项目中,可以将单例模式应用于需要在整个应用程序中共享状态的类,比如配置管理器、日志记录器等。例如,在 Java Web 应用程序中,可以使用单例模式来管理数据库连接池,以确保所有的数据库操作共享同一个连接池。

应用场景:

  • 日志记录器
  • 配置管理器
  • 数据库连接池

示例代码:

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

. 工厂模式(Factory Pattern)

工厂模式用于创建对象,而不需要将对象的创建逻辑暴露给客户端。在项目中,可以使用工厂模式来根据不同的条件创建不同的对象实例。例如,如果有一个产品管理系统,可以使用工厂模式根据产品类型来创建不同的产品对象,而客户端只需要知道如何使用产品对象,而不需要知道如何创建它们。

应用场景:

  • 图形用户界面工具包(GUI Toolkit)
  • 抽象工厂模式可用于创建产品族

示例代码:

public interface Shape {void draw();
}public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing Circle");}
}public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Drawing Rectangle");}
}public class ShapeFactory {public Shape getShape(String shapeType) {if (shapeType == null) {return null;}if (shapeType.equalsIgnoreCase("CIRCLE")) {return new Circle();} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {return new Rectangle();}return null;}
}

3. 观察者模式(Observer Pattern)

观察者模式用于定义对象之间的一对多依赖关系,当一个对象的状态发生变化时,其相关依赖对象都会收到通知并自动更新。在项目中,可以使用观察者模式来实现事件驱动的编程模型。例如,在一个社交媒体应用中,可以使用观察者模式来实现用户之间的关注关系,当被关注用户发布新的内容时,所有关注者都会收到通知。

应用场景:

  • GUI 中的事件处理
  • 发布-订阅系统

示例代码:

import java.util.ArrayList;
import java.util.List;public class Subject {private List<Observer> observers = new ArrayList<>();public void attach(Observer observer) {observers.add(observer);}public void notifyAllObservers() {for (Observer observer : observers) {observer.update();}}
}public abstract class Observer {protected Subject subject;public abstract void update();
}public class ConcreteObserver extends Observer {public ConcreteObserver(Subject subject) {this.subject = subject;this.subject.attach(this);}@Overridepublic void update() {System.out.println("Observer updated");}
}

4. 策略模式(Strategy Pattern)

策略模式用于定义一系列算法,并将每个算法封装到单独的类中,使它们可以互相替换。在项目中,可以使用策略模式来实现不同的算法族,根据不同的情况选择合适的算法。例如,在电商平台中,可以使用策略模式来实现不同的支付方式,让用户可以根据自己的喜好选择支付方式。

应用场景:

  • 文件压缩/解压缩
  • 排序算法

示例代码:

public interface CompressionStrategy {public void compressFile(String fileName);
}public class ZipCompressionStrategy implements CompressionStrategy {@Overridepublic void compressFile(String fileName) {System.out.println("Compressing using Zip strategy");}
}public class RarCompressionStrategy implements CompressionStrategy {@Overridepublic void compressFile(String fileName) {System.out.println("Compressing using RAR strategy");}
}public class Compressor {private CompressionStrategy compressionStrategy;public Compressor(CompressionStrategy compressionStrategy) {this.compressionStrategy = compressionStrategy;}public void compressFile(String fileName) {compressionStrategy.compressFile(fileName);}
}

5、装饰器模式(Decorator Pattern)

装饰器模式是一种结构型设计模式,它允许你在不修改原始类的情况下,动态地给对象添加额外的功能。这种模式通过将对象包装在装饰器类的对象中来实现,使得可以在运行时动态地添加或修改对象的行为。

核心概念

在装饰器模式中,有以下几个核心角色:

  • Component(组件): 定义了一个对象接口,可以动态地给这些对象添加新的职责。
  • ConcreteComponent(具体组件): 实现了 Component 接口,并定义了需要被装饰的对象。
  • Decorator(装饰器): 持有一个指向 Component 对象的引用,并实现了 Component 接口,它的接口与 Component 一致,同时也可以包含一些附加的行为。
  • ConcreteDecorator(具体装饰器): 扩展了 Decorator 类,并添加了一些额外的功能。

应用场景

装饰器模式适用于以下情况:

  • 当需要动态地给对象添加功能,而且这些功能可以在运行时移除时。
  • 当使用继承来扩展对象的功能不切实际或不灵活时。
  • 当需要透明且动态地扩展对象的功能,而不影响其接口时。

在项目中的应用示例

在一个文件处理应用中,可以使用装饰器模式来给文件流添加缓冲功能,而不需要修改文件流的原始实现。

Component:File
public interface File {void read();void write(String data);
}
ConcreteComponent:FileStream
public class FileStream implements File {@Overridepublic void read() {System.out.println("Reading file...");// 读取文件的实现}@Overridepublic void write(String data) {System.out.println("Writing to file: " + data);// 写入文件的实现}
}
Decorator:FileDecorator
public abstract class FileDecorator implements File {protected File file;public FileDecorator(File file) {this.file = file;}@Overridepublic void read() {file.read();}@Overridepublic void write(String data) {file.write(data);}
}
ConcreteDecorator:BufferedFile
public class BufferedFile extends FileDecorator {public BufferedFile(File file) {super(file);}@Overridepublic void read() {System.out.println("Adding buffering functionality...");super.read();// 添加缓冲功能的实现}@Overridepublic void write(String data) {System.out.println("Adding buffering functionality...");super.write(data);// 添加缓冲功能的实现}
}
使用示例
public class Main {public static void main(String[] args) {File file = new FileStream();file = new BufferedFile(file); // 添加缓冲功能file.read();file.write("Some data");}
}

装饰器模式是一种灵活且强大的设计模式,它允许你通过组合对象来动态地添加新的功能,而无需修改现有代码。通过保持接口的一致性,装饰器模式使得客户端可以以透明的方式使用装饰后的对象。这种模式在需要动态地扩展对象功能时非常有用,并且有助于遵循开闭原则。

总结

设计模式是软件开发中非常有价值的工具,它们提供了一种通用的解决方案,可用于解决各种常见的设计问题。通过理解这些设计模式并在项目中加以应用,可以提高代码的可维护性、可扩展性和可重用性。

相关文章:

深入理解常见的设计模式

目录 引言 1. 单例模式&#xff08;Singleton Pattern&#xff09; 应用场景&#xff1a; 示例代码&#xff1a; . 工厂模式&#xff08;Factory Pattern&#xff09; 应用场景&#xff1a; 示例代码&#xff1a; 3. 观察者模式&#xff08;Observer Pattern&#xff09…...

服务器解析漏洞及任意文件下载

1.服务器文件解析漏洞 文件解析漏洞,是指Web容器&#xff08;Apache、nginx、iis等&#xff09;在解析文件时出现了漏洞,以其他格式执行出脚本格式的效果。从而,黑客可以利用该漏洞实现非法文件的解析。 &#xff08;1) Apache linux系统中的apache的php配置文件在/etc/apac…...

ES6扩展运算符——三个点(...)用法详解

目录 1 含义 2 替代数组的 apply 方法 3 扩展运算符的应用 &#xff08; 1 &#xff09;合并数组 &#xff08; 2 &#xff09;与解构赋值结合 &#xff08; 3 &#xff09;函数的返回值 &#xff08; 4 &#xff09;字符串 &#xff08; 5 &#xff09;实现了 Iter…...

限制资源使用

限制资源使用 您需要显示对服务器资源的访问来保护Web应用程序和应用程序数据不受未授权用户的访问。在Java EE Web应用程序中,您可以通过在应用服务器中创建用户和用户组来保护资源免受未经授权的访问。您可以为应用程序定义角色并在部署过程中将角色分配给用户。 1. 创建授权…...

结合Next项目实际认识webpack.splitChunks

本文的目的在于简单的介绍webpack的优化功能配置&#xff1a;splitChunks。 webpack5出于“开箱即用”的目的&#xff0c;将大部分曾经要使用插件的功能集成到了config配置中&#xff0c;因此用户只需要了解如何配置&#xff0c;即可达到优化目的&#xff0c;其中最常使用接触的…...

【Tauri】(2):使用Tauri应用开发,使用开源的Chatgpt-web应用做前端,使用rust 的candle做后端,本地运行小模型桌面应用

视频演示地址 https://www.bilibili.com/video/BV17j421X7Zc/ 【Tauri】&#xff08;2&#xff09;&#xff1a;使用Tauri应用开发&#xff0c;使用开源的Chatgpt-web应用做前端&#xff0c;使用rust 的candle做后端&#xff0c;本地运行小模型桌面应用 1&#xff0c;做一个免…...

C#where T :通用的泛型约束(generic constraint)语法

在C#中&#xff0c;where T :是一种通用的泛型约束&#xff08;generic constraint&#xff09;语法&#xff0c;用于限制泛型类型参数T的特定条件。通过使用泛型约束&#xff0c;我们可以对泛型类型参数进行更具体的限制&#xff0c;以确保在使用泛型时满足特定的要求。 wher…...

vue使用Mars3d弹框嵌套video视频/实时视频(m3u8)使用hls.js

下载hls.js http://mars3d.cn/lib/video/hls/hls.js下载 1.首先绘制地图我使用的天地图 async infoMars3d() {const that this;var mapOptions {scene: {center: {lat: 30.435192,lng: 103.936535,alt: 200000,heading: 359,pitch: -79},highDynamicRange: false},// 方式1&a…...

Python爬虫之Ajax数据爬取基本原理

前言 有时候我们在用 requests 抓取页面的时候&#xff0c;得到的结果可能和在浏览器中看到的不一样&#xff1a;在浏览器中可以看到正常显示的页面数据&#xff0c;但是使用 requests 得到的结果并没有。这是因为 requests 获取的都是原始的 HTML 文档&#xff0c;而浏览器中…...

osg操控器和键盘切换操控器学习

osg提供了很多操控器,在src\osgGA目录下,cpp文件名含有Manipulator的都是操控器,每个这样的cpp表示一种类型的操控器。 名字带 Manipulator 的类都是操控器; 其中KeySwitchMatrixManipulator.cpp文件实现了键盘切换操控器; 操控器是指:操控相机运动,从而实现场景视图…...

LeetCode1143. Longest Common Subsequence——动态规划

文章目录 一、题目二、题解 一、题目 Given two strings text1 and text2, return the length of their longest common subsequence. If there is no common subsequence, return 0. A subsequence of a string is a new string generated from the original string with so…...

利用Windows10漏洞破解密码(保姆级教学)

前言: 本篇博客只是技术分享并非非法传播知识,实验内容均是在虚拟机中进行,并非真实环境 正文: 一.windows10电脑密码破解 1)开启windows10虚拟机,停留在这个页面 2&#xff09;按5次Shift键,出现这个粘滞键,如果没有出现的,则说明漏洞已经修复 3)重新启动,在这个页面的时候…...

apk反编译修改教程系列---简单修改apk默认横竖屏显示 手机端与电脑端同步演示【十一】

往期教程&#xff1a; apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…...

2301: 不定方程解的个数

题目描述 输出不定方程解的个数。在数学中&#xff0c;不定方程是数论中的一个重要课题&#xff0c;在各种比赛中也常常出现. 对于不定方程&#xff0c;有时我们往往只求非负整数解&#xff0c;现有方程axbyc0&#xff0c;其中x、y为未知量且不超过10000&#xff0c;当给定a、…...

vue3学习——封装菜单栏

/Layout/Sidebar/index.vue <script setup lang"ts"> import Sidebar from ./Sidebar.vue // 在下面的代码里 import { useRoute } from vue-router import useUserStore from /store/modules/user.ts // state中存放菜单数据 import useLayoutSetting from /…...

深度学习的进展及其在各领域的应用

深度学习&#xff0c;作为人工智能的核心分支&#xff0c;近年来在全球范围内引起了广泛的关注和研究。它通过模拟人脑的学习机制&#xff0c;构建复杂的神经网络结构&#xff0c;从大量数据中学习并提取有用的特征表示&#xff0c;进而解决各种复杂的模式识别问题。 一、深度…...

blender怎么保存窗口布局,怎么设置默认输出文件夹

进行窗口布局大家都会&#xff0c;按照自己喜好来就行了&#xff0c;设置输出文件夹如图 这些其实都简单。关键问题在于&#xff0c;自己调好了窗口布局&#xff0c;或者设置好了输出文件夹之后&#xff0c;怎么能让blender下次启动的时候呈现出自己设置好的窗口布局&#xff…...

【开源】基于JAVA+Vue+SpringBoot的实验室耗材管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 耗材档案模块2.2 耗材入库模块2.3 耗材出库模块2.4 耗材申请模块2.5 耗材审核模块 三、系统展示四、核心代码4.1 查询耗材品类4.2 查询资产出库清单4.3 资产出库4.4 查询入库单4.5 资产入库 五、免责说明 一、摘要 1.1…...

【ES】--Elasticsearch的分词器详解

目录 一、前言二、分词器原理1、常用分词器2、ik分词器模式3、指定索引的某个字段进行分词测试3.1、采用ts_match_analyzer进行分词3.2、采用standard_analyzer进行分词三、如何调整分词器1、已存在的索引调整分词器2、特别的词语不能被拆开一、前言 最近项目需求,针对客户提…...

【算法】{画决策树 + dfs + 递归 + 回溯 + 剪枝} 解决排列、子集问题(C++)

文章目录 1. 前言2. 算法例题 理解思路、代码46.全排列78.子集 3. 算法题练习1863.找出所有子集的异或总和再求和47.全排列II17.电话号码的字母组合 1. 前言 dfs问题 我们已经学过&#xff0c;对于排列、子集类的问题&#xff0c;一般可以想到暴力枚举&#xff0c;但此类问题用…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

Python实现简单音频数据压缩与解压算法

Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中&#xff0c;压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言&#xff0c;提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...