【设计模式有哪些】
一、创建型模式(Creation Patterns)
1. 单例模式(Singleton)
- 核心思想:保证一个类仅有一个实例,并提供全局访问点。
- 实现方式:
public class Singleton {// 1. 私有静态实例,volatile 保证多线程可见性private static volatile Singleton instance;// 2. 私有构造方法private Singleton() {}// 3. 双重检查锁定(Double-Checked Locking)public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;} } - 场景:
- 数据库连接池(全局唯一,避免重复创建连接)
- 配置管理类(如读取配置文件)
- 优点:节省内存,避免重复创建对象。
- 缺点:需处理多线程安全问题,可能违反单一职责原则。
2. 工厂方法模式(Factory Method)
- 核心思想:定义一个创建对象的接口,但由子类决定实例化哪个类。
- 代码示例:
// 抽象产品 interface Product {void use(); }// 具体产品A class ConcreteProductA implements Product {public void use() {System.out.println("Using Product A");} }// 抽象工厂 abstract class Creator {public abstract Product createProduct(); }// 具体工厂A class ConcreteCreatorA extends Creator {public Product createProduct() {return new ConcreteProductA();} } - 场景:
- 日志记录器(不同日志类型:文件、数据库)
- 跨平台UI组件(不同操作系统创建不同按钮)
- 优点:解耦客户端代码与具体类,扩展性强。
- 缺点:每新增一个产品,需新增一个工厂类。
3. 抽象工厂模式(Abstract Factory)
- 核心思想:创建一组相关或依赖的对象族(例如同一主题下的所有UI组件)。
- 代码示例:
// 抽象产品族:按钮和文本框 interface Button { void render(); } interface TextBox { void input(); }// Windows 风格产品 class WindowsButton implements Button {public void render() { System.out.println("Windows Button"); } } class WindowsTextBox implements TextBox {public void input() { System.out.println("Windows TextBox"); } }// 抽象工厂接口 interface GUIFactory {Button createButton();TextBox createTextBox(); }// Windows 工厂 class WindowsFactory implements GUIFactory {public Button createButton() { return new WindowsButton(); }public TextBox createTextBox() { return new WindowsTextBox(); } } - 场景:
- 跨平台应用开发(同一套UI在不同操作系统下表现不同)
- 游戏中的不同风格资源包(如科幻 vs 中世纪)
- 优点:保证产品族的兼容性。
- 缺点:新增产品族需要修改所有工厂类。
4. 建造者模式(Builder)
- 核心思想:分步骤构造复杂对象,允许不同表示形式。
- 代码示例:
class Computer {private String CPU;private String RAM;// 其他组件...// 建造者内部类public static class Builder {private String CPU;private String RAM;public Builder setCPU(String cpu) {this.CPU = cpu;return this; // 链式调用}public Builder setRAM(String ram) {this.RAM = ram;return this;}public Computer build() {Computer computer = new Computer();computer.CPU = this.CPU;computer.RAM = this.RAM;return computer;}} }// 使用 Computer computer = new Computer.Builder().setCPU("Intel i7").setRAM("32GB").build(); - 场景:
- 生成复杂对象(如HTML文档、SQL查询)
- 链式调用配置参数(如Retrofit、OkHttp的配置)
- 优点:封装对象的构造过程,支持灵活扩展。
- 缺点:代码量增加,适合构造复杂对象。
5. 原型模式(Prototype)
- 核心思想:通过克隆现有对象创建新对象,避免重复初始化。
- 代码示例:
class Prototype implements Cloneable {private String data;public Prototype(String data) {this.data = data;}@Overridepublic Prototype clone() {try {return (Prototype) super.clone();} catch (CloneNotSupportedException e) {return null;}} }// 使用 Prototype original = new Prototype("Original Data"); Prototype copy = original.clone(); - 场景:
- 游戏中的敌人复制(避免重复初始化属性)
- 对象初始化成本高(如数据库数据克隆)
- 优点:性能优化,绕过构造方法。
- 缺点:深拷贝与浅拷贝需谨慎处理。
二、结构型模式(Structural Patterns)
6. 适配器模式(Adapter)
- 核心思想:将一个接口转换成客户端期望的另一个接口。
- 代码示例:
// 旧接口(不兼容) class LegacyPrinter {void printDocument(String text) {System.out.println("Legacy Printer: " + text);} }// 新接口 interface ModernPrinter {void print(String content); }// 适配器类 class PrinterAdapter implements ModernPrinter {private LegacyPrinter legacyPrinter = new LegacyPrinter();public void print(String content) {legacyPrinter.printDocument(content);} } - 场景:
- 旧系统接口适配新系统
- 第三方库的接口封装
- 优点:复用旧代码,解决接口不兼容。
- 缺点:过多适配器会增加代码复杂度。
7. 装饰器模式(Decorator)
- 核心思想:动态地为对象添加职责(不修改原有类)。
- 代码示例:
// 基础组件 interface Coffee {double getCost();String getDescription(); }// 具体组件 class SimpleCoffee implements Coffee {public double getCost() { return 1.0; }public String getDescription() { return "Simple Coffee"; } }// 装饰器基类 abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee coffee) {this.decoratedCoffee = coffee;} }// 具体装饰器:加牛奶 class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) { super(coffee); }public double getCost() { return decoratedCoffee.getCost() + 0.5; }public String getDescription() { return decoratedCoffee.getDescription() + ", Milk"; } }// 使用 Coffee coffee = new MilkDecorator(new SimpleCoffee()); - 场景:
- Java IO流(如
BufferedReader包装FileReader) - Web请求的过滤器链
- Java IO流(如
- 优点:比继承更灵活,支持运行时扩展。
- 缺点:多层装饰可能导致代码复杂。
8. 代理模式(Proxy)
- 核心思想:控制对对象的访问(延迟加载、权限控制等)。
- 代码示例:
interface Image {void display(); }// 真实对象(高成本) class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename = filename;loadFromDisk();}private void loadFromDisk() {System.out.println("Loading image: " + filename);}public void display() {System.out.println("Displaying image: " + filename);} }// 代理类(延迟加载) class ProxyImage implements Image {private RealImage realImage;private String filename;public ProxyImage(String filename) { this.filename = filename; }public void display() {if (realImage == null) {realImage = new RealImage(filename);}realImage.display();} } - 场景:
- 虚拟代理(如图片延迟加载)
- 保护代理(如权限验证)
- 远程代理(如RPC调用)
- 优点:解耦客户端与真实对象,增强控制。
- 缺点:可能引入性能开销。
三、行为型模式(Behavioral Patterns)
9. 观察者模式(Observer)
- 核心思想:定义对象间的一对多依赖关系,当一个对象状态改变时,自动通知依赖它的对象。
- 代码示例:
// 主题(被观察者) interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers(); }// 具体主题(例如天气数据) class WeatherData implements Subject {private List<Observer> observers = new ArrayList<>();private float temperature;public void setTemperature(float temp) {this.temperature = temp;notifyObservers();}public void registerObserver(Observer o) { observers.add(o); }public void removeObserver(Observer o) { observers.remove(o); }public void notifyObservers() {for (Observer o : observers) {o.update(temperature);}} }// 观察者接口 interface Observer {void update(float temperature); }// 具体观察者(例如显示设备) class DisplayDevice implements Observer {public void update(float temperature) {System.out.println("Current Temperature: " + temperature);} } - 场景:
- 事件驱动系统(如GUI按钮点击事件)
- 发布-订阅模型(如消息队列)
- 优点:解耦主题与观察者,支持广播通信。
- 缺点:观察者过多时可能影响性能。
10. 策略模式(Strategy)
- 核心思想:定义一系列算法,使其可以相互替换,且算法的变化独立于客户端。
- 代码示例:
// 策略接口 interface PaymentStrategy {void pay(int amount); }// 具体策略:信用卡支付 class CreditCardPayment implements PaymentStrategy {public void pay(int amount) {System.out.println("Paid " + amount + " via Credit Card");} }// 上下文类(使用策略) class ShoppingCart {private PaymentStrategy strategy;public void setPaymentStrategy(PaymentStrategy strategy) {this.strategy = strategy;}public void checkout(int amount) {strategy.pay(amount);} }// 使用 ShoppingCart cart = new ShoppingCart(); cart.setPaymentStrategy(new CreditCardPayment()); cart.checkout(100); - 场景:
- 支付方式选择(支付宝、微信、银行卡)
- 排序算法切换(快速排序、归并排序)
- 优点:避免多重条件判断,易于扩展新算法。
- 缺点:客户端必须理解不同策略的区别。
11. 责任链模式(Chain of Responsibility)
- 核心思想:将请求沿着处理链传递,直到有一个处理者处理它。
- 代码示例:
abstract class Handler {protected Handler nextHandler;public void setNext(Handler handler) {this.nextHandler = handler;}public abstract void handleRequest(int request); }// 具体处理者A class ConcreteHandlerA extends Handler {public void handleRequest(int request) {if (request <= 10) {System.out.println("Handler A processes request " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}} }// 使用 Handler chain = new ConcreteHandlerA(); chain.setNext(new ConcreteHandlerB()); chain.handleRequest(5); // 由A处理 chain.handleRequest(20); // 由B处理 - 场景:
- Web框架的过滤器链(如Spring Security)
- 审批流程(如请假申请的多级审批)
- 优点:动态调整处理链,解耦发送者和接收者。
- 缺点:请求可能未被处理。
四、如何实际应用设计模式?
- 核心原则:先理解问题,再选择模式,避免为了用模式而用模式。
- 常见误区:
- 过度设计:简单问题强行套用复杂模式。
- 模式混用:多个模式叠加导致代码混乱。
- 学习建议:
- 从简单模式入手(如工厂、单例、观察者)。
- 结合开源框架(如Spring、JDK源码)学习模式的应用。
- 在重构中实践模式,逐步替换旧代码。
希望这些详细的解释和代码示例能帮助你深入理解设计模式!如果需要某个模式的进一步扩展,可以告诉我。
相关文章:
【设计模式有哪些】
一、创建型模式(Creation Patterns) 1. 单例模式(Singleton) 核心思想:保证一个类仅有一个实例,并提供全局访问点。实现方式:public class Singleton {// 1. 私有静态实例,volatil…...
基于SpringBoot+Vue的幼儿园管理系统+LW示例参考
1.项目介绍 系统角色:管理员、教师、普通用户功能模块:用户管理、教师管理、班级管理、幼儿信息管理、会议记录管理、待办事项、职工考核、请假信息、缴费信息、体检管理、资源管理、原料管理、菜品信息管理等技术选型:SpringBoot࿰…...
默认参数 d = {} 的陷阱
默认参数 d {} 的陷阱 问题需求思路代码实现默认参数d {}的陷阱解决办法1、在函数外为每个字符串创建空字典统计词频2、函数改为每次调用时创建新字典,避免数据污染 举一反三 问题需求 统计两个字符串的中文词语出现次数 思路 先使用jieba库分词功能处理字符串…...
Python 常用内建模块-argparse
目录 argparse 小结 argparse 在命令行程序中,经常需要获取命令行参数。Python内置的sys.argv保存了完整的参数列表,我们可以从中解析出需要的参数: # copy.py import sys print(sys.argv) source sys.argv[1] target sys.argv[2] # TOD…...
案例5_3: 6位数码管静态显示
文章目录 文章介绍效果图仿真图复习知识:代码思考 文章介绍 第5章 学习数码管,使用6位数码管进行静态显示 效果图 仿真图 新建一个干净的5_3文件夹,用于存放新画的仿真图 除单片机最小系统外,新增3个元器件,分别是&…...
Profinet转Modbus RTU/TCP以太网通讯处理器
Profinet转Modbus RTU/TCP以太网通讯处理器 在当今的工业自动化领域,各种通讯协议和标准层出不穷。 其中,Profinet和Modbus作为两种广泛应用的通讯协议,分别在不同的应用场景中发挥着重要作用。 然而,当需要将这两种协议进行转换…...
3倍训练速度+40%显存节省!Mamba+Transformer 仅用一半时间,性能提升80%!
在人工智能领域,Mamba与Transformer的结合正在成为研究热点,为自然语言处理和多模态任务带来新的突破。 最新研究表明,通过将Mamba架构与Transformer的强大编码能力相结合,模型在处理复杂的多模态数据时的效率提升了50%ÿ…...
春秋云境刷题1
CVE-2022-29464 靶标介绍: WSO2文件上传漏洞(CVE-2022-29464)是Orange Tsai发现的WSO2上的严重漏洞。该漏洞是一种未经身份验证的无限制任意文件上传,允许未经身份验证的攻击者通过上传恶意JSP文件在WSO2服务器上获得RCE。 Git…...
台式机电脑组装---电源
台式机电脑组装—电源 22 33 主板供电是聚集了12V,5V,3.3V的24pin CPU供电的话主要是12V的44pin供电 44pin合并之后,就是8pin 55 SATA硬盘会使用饼io口取电,从电源获取12v,5v,3.3v的电 33...
10-BST(二叉树)-建立二叉搜索树,并进行前中后遍历
题目 来源 3540. 二叉搜索树 - AcWing题库 思路 建立二叉搜索树(注意传参时用到了引用,可以直接对root进行修改),同时进行递归遍历;遍历可以分前中后三种写,也可以用标志来代替合在一起。其余详见代码。…...
蓝桥杯备考:贪心问题之淘淘摘苹果
这是淘淘摘苹果普通版,很可爱的一道题,我们不多陈述,直接上代码 #include <iostream> using namespace std; const int N 15; int a[N]; int main() {for(int i 1;i<10;i){cin >> a[i];}int x;cin >> x;x30;int cnt …...
VSTO(C#)Excel开发 系列目录 含源码发布
初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…...
在 Ubuntu 下通过 Docker 部署 Nginx+PHP-FPM 服务器
引言 大家好,今天我们来聊聊如何在 Ubuntu 下通过 Docker 部署 Nginx 和 PHP-FPM 服务器。Docker 是一个开源的容器化平台,可以轻松地打包、分发和管理应用程序。而 Nginx 是一个高性能的 HTTP 服务器和反向代理服务器,PHP-FPM 则是 PHP 的一…...
Git使用和原理(3)
1.远程操作 1.1分布式版本控制系统 我们⽬前所说的所有内容(⼯作区,暂存区,版本库等等),都是在本地!也就是在你的笔记本或者 计算机上。⽽我们的 Git 其实是分布式版本控制系统!什么意思呢&a…...
【ELK】节省存储 之 压缩存储方式调整
目录 集群版本: 7.17.6 解释几个概念: 段(Segment) 合并(Merge) 索引设置: 压缩方式(index.codec): 测试设置前提条件 对比 在创建的时候指定压缩类型(index.codec) 对比 在…...
导出的使用
在web开发中,导出是很常见的一个功能,当我进行个人项目练习的时候,导出的时候无法控制列宽以及居中样式,后续发现导出插件无法进行修改,整个插件较为简便易懂的同时,对于EX的控制较为简陋,很多东…...
博客图床 VsCode + PigGo + 阿里云OSS
关键字 写博客,图床,VsCode,PigGo,阿里云OSS 背景环境 我想把我在本地写的markdown文档直接搬到CSDN上和博客园上,但是图片上传遇到了问题。我需要手动到不同平台上传文件,非常耗费时间和经历。 为了解决…...
鸿蒙开源硬件:重构万物智联生态的底层基座与未来机遇
一、从生态裂变到产业重构:开源鸿蒙的崛起之路 自 2020 年开源至今,OpenHarmony 社区以惊人的发展速度重塑智能终端操作系统格局。数据显示,其代码量已从初始的 700 万行激增至 1.2 亿行,汇聚超 8200 名开发者及 70 余家核心共建…...
C++之list类及模拟实现
目录 list的介绍 list的模拟实现 定义节点 有关遍历的重载运算符 list的操作实现 (1)构造函数 (2)拷贝构造函数 (3)赋值运算符重载函数 (4)析构函数和clear成员函数 (5)尾…...
SwinTransformer 改进:添加DoubleAttention模块提升上下文语义提取能力
目录 1. DoubleAttention模块 2. SwinTransformer + DoubleAttention 3. 完整代码 Tips:融入模块后的网络经过测试,可以直接使用,设置好输入和输出的图片维度即可 1. DoubleAttention模块 DoubleAttention 是一种用于计算机视觉任务的注意力机制,旨在通过双重注意力机制…...
在Electron中实现实时下载进度显示的完整指南
在开发Electron应用时,提供良好的用户体验至关重要,尤其是在下载大文件时。用户需要知道下载进度、预计完成时间以及当前下载速度。本文将详细介绍如何在Electron应用中实现实时下载进度显示功能,从主进程到渲染进程的完整流程。 技术栈是ele…...
java生成一个可以下载的word文件
在 Java 里,你能够借助 Apache POI 库来生成 Word 文件,并且实现文件下载功能。下面为你详细介绍实现步骤和示例代码。 1. 添加依赖 若使用 Maven 项目,需在 pom.xml 里添加 Apache POI 的依赖: <dependencies><depen…...
MacBook部署达梦V8手记
背景 使用Java SpringBootDM开发Web应用,框架有License,OSX加载dll失败,安装了Windows 11,只有一个C盘,达梦安装后因为C盘权限问题,创建数据库失败,遂采用Docker容器方式部署。 下载介质 官网在…...
外贸 B2B 平台没落?多语言批发系统正在崛起
近年来,全球外贸行业正在发生快速变化,传统的 B2B 平台正面临越来越多的挑战,尤其是在面对新兴的多语言批发系统时。这种变化不仅影响了供应商和买家之间的交易方式,也正在推动外贸行业的数字化升级和转型。今天,让我们…...
[spring] Spring JPA - Hibernate 多表联查 1
[spring] Spring JPA - Hibernate 多表联查 之前在 [spring] spring jpa - hibernate 名词解释&配置 和 [spring] spring jpa - hibernate CRUD 简单的学习了一下怎么使用 Hibernate 实现 CRUD 操作,不过涉及到的部分都是逻辑上比较简单的实现——只在一张表上…...
鸿蒙Next开发实战教程—电影app
最近忙忙活活写了不少教程,但是总感觉千篇一律,没什么意思,大家如果有感兴趣的项目可以私信给幽蓝君写一写。 今天分享一个电影App。 这个项目也比较简单,主要是一些简单页面的开发和本地视频的播放以及横竖屏切换。 页面搭建以…...
共享栈 线程局部存储 线程互斥 线程同步 消费者生产者模型
共享栈 第一个主线程会在栈区 而当其他线程创建时实在共享区动态申请的栈区 线程局部存储 __thread 关键字 与编译有关 全局变量是被线程共享的 每个线程都能看到 修改 但是如果对该全局变量加上__thread关键字后 该全局变量就不会被共享 将变量在库中的每一个线程的属…...
停车场停车位数据集,标注停车位上是否有车,平均正确识别率99.5%,支持yolov5-11, coco json,darknet,xml格式标注
停车场停车位数据集,标注停车位上是否有车,平均正确识别率98.0%,支持yolov5-11, coco json,darknet,xml格式标注 数据集-识别停车场所有车辆的数据集 数据集分割 一共184张图片 训练组 89&am…...
【Go】运算符笔记
基本数学运算 Go 语言支持常见的 算术运算符,用于执行数学计算。 运算符说明加法-减法*乘法/除法%取余自增--自减 整数运算只能得到整数部分 package mainimport ("fmt""math" )func main() {go_math() }func go_math() {x, y : 8, 5fmt.Pr…...
ssm框架之mybatis框架讲解
1,Mybatis 1.1 Mybatis概述 1.1.1 Mybatis概念 MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发 MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2…...
