当前位置: 首页 > 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…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...