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

常见的几种设计模式(详细)——应用场景和实现方式

文章目录

  • 🎯单例模式
    • 应用
    • 实现
  • 🏭工厂模式
    • 应用
    • 实现
  • ❓策略模式
    • 应用
    • 实现
  • 🧑‍⚖️代理模式
    • 应用
    • 实现
  • 🔍观察者模式(发布订阅模式)
    • 应用
    • 实现
  • 🧰装饰器模式
    • 应用
    • 实现
  • 📰模版方法模式
    • 应用
    • 实现
  • ⛓️责任链模式
    • 应用
    • 实现

🎯单例模式

整个程序运行过程中,类只有一个实例,减少内存消耗

应用

  1. 资源管理:需要共享的资源如数据库连接池线程池等,确保只有一个实例管理这些资源
  2. 全局配置:配置类
  3. 日志记录器:在多线程或分布式环境中确保日志记录器唯一性

实现

实现时注意:

  1. 构造器私有化,防止篡改
  2. 只暴露一个公共的获取实例的方法
  3. 是否线程安全
  1. 饿汉式:线程安全,类加载的时候就实例化

    public class Singleton{private static final Singleton instance = new Singleton();private Singleton(){}public static Singleton getInstance(){return instance;}
    }
    
  2. 懒汉式:线程不安全,使用到时再实例化

    public class Singleton{private static Singleton instance ;private Singleton(){}public static Singleton getInstance(){if(instance == null){instance = new Singleton();}return instance;}
    }
    
  3. 双重检查锁:懒汉式的优化,线程安全(使用volatile防止指令重排序)

    public class Singleton{private static volatile Singleton instance; //使用volatile防止指针重排序private Singleton(){}public static Singleton getInstance(){if(instance == null){  //第一次检查synchronized(Singleton.class){if(instance == null){  //第二次检查,保证线程安全instance = new Singleton();}}}}
    }
    
  4. 静态内部类:利用类加载机制实现懒加载和线程安全

    public class Singleton {private Singleton() {}private static class Holder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return Holder.INSTANCE;}
    }
  5. 枚举单例:简单且防止反射和序列化攻击

    public enum Singleton{INSTANCE;
    }Singleton instance = Singleton.INSTANCE;
    

防止反射入侵:在构造器中添加一个判断,如果对象存在,则抛出异常

序列化和反序列化安全:添加一个readResolve()方法,在进行反序列化时会执行readResolve()方法,确保只有一个实例存在

🏭工厂模式

封装对象的创建逻辑,减低耦合

应用

动态创建不同类型的对象

实现

产品接口、产品实现类、工厂类

// 产品接口
public interface Product {void use();
}// 具体产品A
public class ConcreteProductA implements Product {@Overridepublic void use() {System.out.println("Using ConcreteProductA");}
}// 具体产品B
public class ConcreteProductB implements Product {@Overridepublic void use() {System.out.println("Using ConcreteProductB");}
}// 简单工厂类
public class SimpleFactory {public static Product createProduct(String type) {switch (type) {case "A":return new ConcreteProductA();case "B":return new ConcreteProductB();default:throw new IllegalArgumentException("Unknown product type");}}
}// 客户端代码
public class Client {public static void main(String[] args) {Product productA = SimpleFactory.createProduct("A");productA.use(); // Output: Using ConcreteProductAProduct productB = SimpleFactory.createProduct("B");productB.use(); // Output: Using ConcreteProductB}
}

❓策略模式

封装不同的算法,允许运行时选择不同的策略

应用

同一个业务使用不同的策略

  1. 支付系统
  2. 数据压缩
  3. 日志策略

实现

策略接口、策略实现类(不同策略)、上下文类

// 策略接口
interface Strategy {void execute();
}// 具体策略A
class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("Executing Strategy A");}
}// 具体策略B
class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("Executing Strategy B");}
}// 上下文类
class Context {private Strategy strategy;public void setStrategy(Strategy strategy) {this.strategy = strategy;}public void executeStrategy() {if (strategy != null) {strategy.execute();} else {System.out.println("No strategy set");}}
}// 客户端
public class Main {public static void main(String[] args) {Context context = new Context();Strategy strategyA = new ConcreteStrategyA();Strategy strategyB = new ConcreteStrategyB();context.setStrategy(strategyA);context.executeStrategy(); // Output: Executing Strategy Acontext.setStrategy(strategyB);context.executeStrategy(); // Output: Executing Strategy B}
}

🧑‍⚖️代理模式

代理对象控制对目标对象的访问

应用

在不修改原来代码的基础上,实现对目标对象的控制和管理

  1. 权限验证
  2. 性能优化:通过代理实现缓存或延迟加载以提高系统性能
  3. 远程访问:客户端访问远程对象时,通过代理封装远程调用细节
  4. 日志记录:在方法调用时添加日志记录功能

实现

接口、实现类、代理类(静态代理)

public interface Subject{void request();
}public RealSubject implements Subject{@Overridepublic void request(){System.out.println("RealSubject request");}
}public class Proxy implements Subject{private RealSubject realSubject;@Overridepublic void request(){if(realSubject == null)realSubject = new RealSubject();System.out.println("before");realSubject.request();System.out.println("after");}
}public class Main{public static void main(String[] args){Subject proxy = new Proxy();proxy.request();}
}

🔍观察者模式(发布订阅模式)

一个对象状态变化时,依赖它的对象会收到通知

应用

  1. 事件驱动系统:用户操作界面,通过监听事件触发响应
  2. 系统间通信:某个模块发生变化,通知多个依赖模块
  3. 订阅:数据更新,通知所有订阅者(推送通知)

实现

观察者接口、被观察者接口、观察者类、被观察者类

// 观察者接口
interface Observer {void update(String message);
}// 被观察者接口
interface Subject {void addObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}// 具体被观察者
class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();private String state;@Overridepublic void addObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(state);}}public void setState(String state) {this.state = state;notifyObservers();}
}// 具体观察者
class ConcreteObserver implements Observer {private String name;public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " received update: " + message);}
}// 客户端
public class Main {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();Observer observer1 = new ConcreteObserver("Observer1");Observer observer2 = new ConcreteObserver("Observer2");subject.addObserver(observer1);subject.addObserver(observer2);subject.setState("New State 1");subject.setState("New State 2");}
}

🧰装饰器模式

不改变原始类,在其基础上动态扩展功能

应用

  1. 动态扩展功能:对现有对象添加功能,但不希望通过继承方式
  2. 不同功能的组合
  3. 透明扩展:客户端无需了解对象是否被装饰过

实现

组件接口、具体组件实现类、装饰器抽象类、具体装饰器

// 组件接口
interface Component {void operation();
}// 具体组件
class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}// 装饰器抽象类
abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}// 具体装饰器A
class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation();System.out.println("ConcreteDecoratorA added behavior");}
}// 具体装饰器B
class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}@Overridepublic void operation() {super.operation();System.out.println("ConcreteDecoratorB added behavior");}
}// 客户端
public class Main {public static void main(String[] args) {Component component = new ConcreteComponent();Component decoratorA = new ConcreteDecoratorA(component);Component decoratorB = new ConcreteDecoratorB(decoratorA);decoratorB.operation();// Output:// ConcreteComponent operation// ConcreteDecoratorA added behavior// ConcreteDecoratorB added behavior}
}

📰模版方法模式

定义一个逻辑框架,把具体的实现留给子类

应用

  1. 定义算法骨架
  2. 复用公共逻辑

例:抽象类、继承抽象类

​ 不同支付渠道的流程都是一样的,包括:前置的参数检查、核心支付逻辑、后置的检查等,可以抽象成一个模版方法(抽象类),不同支付渠道的实现类继承它,并实现支付逻辑。

实现

抽象类、继承抽象类

// 抽象类
abstract class DataProcessor {// 模板方法public final void process() {readData();processData();writeData();}protected abstract void readData(); // 读取数据protected abstract void processData(); // 处理数据protected void writeData() { // 写入数据System.out.println("Writing data to output.");}
}// 具体实现类A
class CSVDataProcessor extends DataProcessor {@Overrideprotected void readData() {System.out.println("Reading data from CSV file.");}@Overrideprotected void processData() {System.out.println("Processing CSV data.");}
}// 具体实现类B
class JSONDataProcessor extends DataProcessor {@Overrideprotected void readData() {System.out.println("Reading data from JSON file.");}@Overrideprotected void processData() {System.out.println("Processing JSON data.");}
}// 客户端
public class Main {public static void main(String[] args) {DataProcessor csvProcessor = new CSVDataProcessor();csvProcessor.process();DataProcessor jsonProcessor = new JSONDataProcessor();jsonProcessor.process();}
}

⛓️责任链模式

将多个对象连接成一条链,沿着这条链传递请求,让每个对象都有机会处理请求,请求会顺着链传递,直到某个对象可以处理。

应用

不同级别处理

  1. 审批流程
  2. 日志系统(不同级别的日志记录)

实现

抽象类、继承抽象类

// 处理器接口
abstract class Handler {protected Handler nextHandler;public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}public abstract void handleRequest(String request);
}// 具体处理器A
class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if ("A".equals(request)) {System.out.println("ConcreteHandlerA handled request: " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("No handler for request: " + request);}}
}// 具体处理器B
class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if ("B".equals(request)) {System.out.println("ConcreteHandlerB handled request: " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);} else {System.out.println("No handler for request: " + request);}}
}// 客户端
public class Main {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setNextHandler(handlerB);handlerA.handleRequest("A"); // Output: ConcreteHandlerA handled request: AhandlerA.handleRequest("B"); // Output: ConcreteHandlerB handled request: BhandlerA.handleRequest("C"); // Output: No handler for request: C}
}

相关文章:

常见的几种设计模式(详细)——应用场景和实现方式

文章目录 &#x1f3af;单例模式应用实现 &#x1f3ed;工厂模式应用实现 ❓策略模式应用实现 &#x1f9d1;‍⚖️代理模式应用实现 &#x1f50d;观察者模式&#xff08;发布订阅模式&#xff09;应用实现 &#x1f9f0;装饰器模式应用实现 &#x1f4f0;模版方法模式应用实现…...

SonarQube

不同版本的sonarqube需要不同版本的数据库、jdk环境。这个看文档然后确定要求 &#xff08;有时候文档里标注的系统要求是不行的。比如要求内存2G&#xff0c;但是实际上是不够的&#xff0c;要注意&#xff09; 我安装的&#xff1a; 官方文档 Prerequisites and overview…...

Nginx 之Rewrite 使用详解

文章目录 1. 概述2. Rewrite 指令 2.1 指令语法2.2 Flag 标记说明 3. Rewrite 与 Location 3.1 Location 分类3.2 Rewrite 和 Location 比较 4. Rewrite 实际场景 4.1 基于域名的跳转4.2 基于客户端 IP 访问跳转4.3 基于参数匹配的跳转4.4 基于目录下所有 PHP 文件跳转4.5 基于…...

注册Gmail如何跳过手机验证环节?

很多小伙伴在注册Gmail的时候都会遇到一个难题&#xff1a;手机号码验证&#xff0c;有可能包括了“手机号无法验证” “国内手机号验证失败” “收不到验证码”等等问题&#xff0c;但 根据真实案例&#xff0c;还有部分人则是“幸运地”没有手机号验证环节&#xff0c;那么今…...

WordPress自助建站全攻略

一、基础概念与核心优势 WordPress自助建站是一种无需编程即可搭建网站的平台&#xff0c;基于开源CMS系统&#xff0c;支持高度定制化。其核心优势主要体现在&#xff1a; 易用性&#xff1a;拖拽式编辑器和直观的后台操作&#xff0c;适合零基础用户快速上手。低成本&#x…...

TreeSet(单列集合)

TreeSet 是 Java 集合框架中的一种实现了 Set 接口的类&#xff0c;它通过一个红黑树&#xff08;Red-Black Tree&#xff09;来存储元素。由于使用了树结构&#xff0c;TreeSet 保证了元素的有序性&#xff0c;并且不允许重复元素。 1. TreeSet 的基本特性 有序性&#xff1…...

Elasticsearch:同义词在 RAG 中重要吗?

作者&#xff1a;来自 Elastic Jeffrey Rengifo 及 Toms Mura 探索 RAG 应用程序中 Elasticsearch 同义词的功能。 同义词允许我们使用具有相同含义的不同词语在文档中搜索&#xff0c;以确保用户无论使用什么确切的词语都能找到他们所寻找的内容。你可能会认为&#xff0c;由于…...

Docker安装分布式vLLM

Docker安装分布式vLLM 1 介绍 vLLM是一个快速且易于使用的LLM推理和服务库&#xff0c;适合用于生产环境。单主机部署会遇到显存不足的问题&#xff0c;因此需要分布式部署。 分布式安装方法 https://docs.vllm.ai/en/latest/serving/distributed_serving.html2 安装方法 …...

可视化实操记录(自用)

流程 读取数据 original_data pd.read_csv(“Penguins.csv”) original_data.head() 评估和清理数据 cleaned_data original_data.copy() #备份 结构 original_data.sample(5) 数据符合“每个变量为一列&#xff0c;每个观察值为一行&#xff0c;每种类型的观察单位为一…...

二叉树的遍历方式和子问题思路

目录 二叉树的遍历&#xff1a; 前序遍历&#xff1a; 中序遍历&#xff1a; 后序遍历&#xff1a; 二叉树的基本操作&#xff1a; 求树的结点个数&#xff08;递归遍历思路&#xff09;&#xff1a; 求树的结点个数&#xff08;子问题思路&#xff09;&#xff1a; 求树的…...

运用Deek Seeker协助数据分析

我的数据源有两张表&#xff0c;一个是每日销售表(字段有日期、产品名称、实际销量)&#xff0c;一个是每月目标表(字段有年度月份、产品名称、目标销量);我的需求是&#xff0c;按月、按年来统计每个产品的目标完成情况请问用PowerBl进行分析&#xff0c;应该如何建立数据模型…...

服务器之连接简介(Detailed Explanation of Server Connection)

一台服务器最大能支持多少连接&#xff1f;一台客户端机器最多能发起多少条连接&#xff1f;&#xff1f; 我们知道TCP连接&#xff0c;从根本上看其实就是client和server端在内存中维护的一组【socket内核对象】&#xff08;这里也对应着TCP四元组&#xff1a;源IP、源端口、…...

低空经济:开启未来空中生活的全新蓝海

引言 随着科技的进步&#xff0c;我们不再仅仅依赖地面交通和传统物流。你是否曾幻想过&#xff0c;未来的某一天&#xff0c;快递、外卖可以像魔法一样直接从空中送到你手中&#xff1f;或者&#xff0c;你能乘坐小型飞行器&#xff0c;快速穿梭于城市之间&#xff0c;告别拥堵…...

主动视觉可能就是你所需要的:在双臂机器人操作中探索主动视觉

AV-ALOHA 系统使用用于 AV 的 VR 耳机实现直观的数据收集&#xff0c;并且 用于作的 VR 控制器或引线臂。这有助于捕捉全身和头部 远程作我们的真实和模拟系统的运动&#xff0c;记录来自 6 个的视频 不同的摄像头&#xff0c;并为我们的 AV 仿制学习策略提供训练数据。 加州大…...

洛谷 P6419 COCI2014/2015 #1 Kamp 题解

题意 一颗树 n n n 个点&#xff0c; n − 1 n-1 n−1 条边&#xff0c;经过每条边都要花费一定的时间&#xff0c;任意两个点都是联通的。 有 k k k 个人&#xff08;分布在 k k k 个不同的点&#xff09;要集中到一个点举行聚会。 聚会结束后需要一辆车从举行聚会的这点…...

在 Vue 项目中使用 SQLite 数据库的基础应用

目录 一、环境准备二、数据库连接与操作1. 创建数据库连接2. 创建表3. 插入数据4. 查询数据5. 更新数据6. 删除数据 三、在 Vue 组件中使用 SQLite 一、环境准备 安装 Node.js 和 npm&#xff1a;确保已安装 Node.js 和 npm。 创建 Vue 项目&#xff1a;使用 Vue CLI 创建一个…...

AI会话问答的页面滚动处理(参考deepseek页面效果)

近期在接入deepseekR1的深度思考&#xff0c;研究了下deepseek官网的滚动效果&#xff0c;大概如下&#xff1a;用户发出消息后&#xff0c;自动滚动到页面最底部&#xff0c;让最新消息展示在视野中&#xff0c;这时候&#xff0c;我们先处理一次滚动&#xff1a; const scrol…...

GRN前沿:DGCGRN:基于有向图卷积网络的基因调控网络推理

1.论文原名&#xff1a;Inference of gene regulatory networks based on directed graph convolutional networks 2.发表日期&#xff1a;2024 DGCGRN框架 中心节点和节点的构建 局部增强策略 1. 问题背景 在基因调控网络中&#xff0c;许多节点的连接度较低&#xff08;即…...

MongoDB 入门操作指南

文章目录 MongoDB 入门操作指南1. 连接到 MongoDB 数据库2. 查看当前数据库3. 显示所有数据库4. 切换或创建数据库5. 查看当前数据库中的所有集合6. 创建集合7. 插入文档插入单个文档插入多个文档 8. 查询文档查询所有文档查询匹配条件的文档格式化查询输出 9. 更新文档更新单个…...

共享设备管理难?MDM助力Kiosk模式一键部署

目录 1. 简化设备部署与配置&#xff1a;实现一键式部署 2. 自动化应用更新与内容推送&#xff1a;确保设备始终保持最新状态 3. 权限控制与设备安全&#xff1a;防止滥用与数据泄露 4. 远程管理与故障诊断&#xff1a;保障设备长期稳定运行 5. 数据分析与报告&#xff1a…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...