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

设计模式:代理模式

代理模式是很常见的设计模式,即使没有专门学习过这种设计模式,在工作中也一定用过这种设计模式。在实际生活中,代理模式也是常见的,比如内阁首辅相对于皇帝,前者是后者的代理,内阁首辅收到奏折时,往往也要做一些预处理和后处理。

当我们需要给原始类增加一些功能、日志、性能监控时,通过修改原始类当然是可以实现的,但是这样就侵入了原来的逻辑,违背了开闭原则。并且新增的功能与原有的功能本来就属于不同范畴的功能。

在不修改原始类的基础上,增加新的功能,就需要用到代理模式。有些类也是无法修改的,这种情况下,只能使用代理模式。

在平时的开发中,为了代码使用方便,我们往往会对一些原始的接口进行封装。在原始接口的基础上增加一些功能或者日志。这样我们在使用对应功能的时候,就可以直接使用我们封装的接口,而不是原始接口,这就是代理模式。

如下是在std::thread的基础上封装的Thread类,通过该类可以设置线程的名字。为了在创建线程的时候指定线程的名字,封装了Thread类,Thread可以看作std::thread的代理类。

#include <iostream>
#include <thread>
#include <unistd.h>class Thread {public:template <class Function, class... Args>Thread(std::string const& name, Function&& f, Args&&... args) noexcept: internal_(std::forward<Function>(f), std::forward<Args>(args)...) {set_name(name);}virtual ~Thread() noexcept {if (internal_.joinable()) {internal_.join();}}bool joinable() const noexcept { return internal_.joinable(); }void join() {if (joinable()) {internal_.join();}}std::thread::native_handle_type native_handle() noexcept { return internal_.native_handle(); }private:void set_name(std::string const& name) noexcept {if (!name.empty()) {uint64_t const thread_name_max{15};if (name.length() > thread_name_max) {pthread_setname_np(native_handle(), name.substr(0, thread_name_max).c_str());} else {pthread_setname_np(native_handle(), name.c_str());}}}private:std::thread internal_;};int main() {Thread t("testthread", [](){std::cout << "thread enter\n";sleep(10);std::cout << "thread exit\n";});t.join();return 0;
}

1静态代理 

静态代理,就是针对一个原始类,实现一个代理类,这个代理类只能对这一个原始类起到代理的作用。如下代码,是代理模式的典型使用方式,代理类与原始类实现相同的接口,代理类中有一个属性是原始类。

#include <iostream>// 接口
class Subject {
public:virtual void Request() const = 0;virtual ~Subject() = default;
};// 原始类
class RealSubject : public Subject {
public:void Request() const override {std::cout << "RealSubject: 处理请求" << std::endl;}
};// 代理类
class Proxy : public Subject {
private:RealSubject* real_subject_;public:Proxy() : real_subject_(new RealSubject()) {}~Proxy() {delete real_subject_;}void Request() const override {std::cout << "Proxy: 预处理请求" << std::endl;real_subject_->Request();std::cout << "Proxy: 后续处理" << std::endl;}
};int main() {Proxy proxy;proxy.Request();return 0;
}

2动态代理

使用静态代理,如果原始类很多的话,那么针对每一个原始类,都要实现一个代理类,这样会造成类的数量成倍的增加。为了解决这个问题,出现了动态代理。

如下代码,是动态代理的例子,动态代理类是一个类模板,该代理类代理的是那个类通过模板参数指定。原始类、预处理函数、后处理函数,均通过构造函数的的参数进行传递。

#include <iostream>
#include <functional>
#include <memory>// 抽象类
class IComponent {
public:virtual void Operation() = 0;virtual ~IComponent() = default;
};// 原始类
class ConcreteComponent : public IComponent {
public:void Operation() override {std::cout << "ConcreteComponent: 核心操作" << std::endl;}
};// 代理类
template <typename T>
class DynamicProxy : public IComponent {
private:std::unique_ptr<T> target_;std::function<void()> pre_handler_;std::function<void()> post_handler_;public:DynamicProxy(std::unique_ptr<T> target,std::function<void()> pre,std::function<void()> post): target_(std::move(target)),pre_handler_(pre),post_handler_(post) {}void Operation() override {// 前置处理if (pre_handler_) pre_handler_();// 委托调用target_->Operation();// 后置处理if (post_handler_) post_handler_();}
};int main() {// 创建动态代理(可运行时配置)auto proxy = std::make_unique<DynamicProxy<ConcreteComponent>>(std::make_unique<ConcreteComponent>(),[]() { std::cout << "DynamicProxy: 预处理" << std::endl; },[]() { std::cout << "DynamicProxy: 后续处理" << std::endl; });proxy->Operation();return 0;
}

相关文章:

设计模式:代理模式

代理模式是很常见的设计模式&#xff0c;即使没有专门学习过这种设计模式&#xff0c;在工作中也一定用过这种设计模式。在实际生活中&#xff0c;代理模式也是常见的&#xff0c;比如内阁首辅相对于皇帝&#xff0c;前者是后者的代理&#xff0c;内阁首辅收到奏折时&#xff0…...

141,【1】buuctf web [SUCTF 2019]EasyWeb

进入靶场 代码审计 <?php // 定义函数get_the_flag&#xff0c;功能是处理文件上传相关操作 function get_the_flag() {// 注释说明&#xff1a;webadmin会每隔20分钟删除用户上传的文件$userdir "upload/tmp_" . md5($_SERVER[REMOTE_ADDR]);// 检查用户目录…...

破解微服务疑难杂症:2025年全解决方案

微服务架构已经成为现代软件开发的主流选择&#xff0c;其优势在于能够将复杂的系统拆分为独立的服务模块&#xff0c;方便开发和维护。然而&#xff0c;在微服务的实施过程中&#xff0c;开发者往往会面临许多挑战&#xff0c;如服务间通信、数据一致性、性能优化和故障处理等…...

Node.js 中的 Event 模块详解

Node.js 中的 Event 模块是实现事件驱动编程的核心模块。它基于观察者模式&#xff0c;允许对象&#xff08;称为“事件发射器”&#xff09;发布事件&#xff0c;而其他对象&#xff08;称为“事件监听器”&#xff09;可以订阅并响应这些事件。这种模式非常适合处理异步操作和…...

EasyRTC嵌入式WebRTC视频通话SDK支持Web浏览器、Linux、ARM、Android、iOS

随着互联网技术的飞速发展&#xff0c;实时通信&#xff08;RTC&#xff09;已经成为现代应用中不可或缺的一部分。无论是视频会议、在线教育、远程医疗&#xff0c;还是社交娱乐&#xff0c;实时通信技术都在其中扮演着重要角色。 然而&#xff0c;WebRTC技术在PC和移动端的支…...

pycharm社区版有个window和arm64版本,到底下载哪一个?还有pycharm官网

首先pycharm官网是这一个。我是在2025年2月16日9:57进入的网站。如果网站还没有更新的话&#xff0c;那么就往下滑一下找到 community Edition,这个就是社区版了免费的。PyCharm&#xff1a;适用于数据科学和 Web 开发的 Python IDE 适用于数据科学和 Web 开发的 Python IDE&am…...

【玩转全栈】----Django模板语法、请求与响应

目录 一、引言 二、模板语法 三、传参 1、视图函数到模板文件 2、模板文件到视图函数 四、引入静态文件 五、请求与响应 ?1、请求 2、响应 六、综合小案例 1、源码展示 2、注意事项以及部分解释 3、展示 一、引言 像之前那个页面&#xff0c;太过简陋&#xff0c;而且一个完整…...

网络安全:挑战、技术与未来发展

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 在数字化时代&#xff0c;网络安全&#xff08;Cybersecurity&#xff09;已成为全球关注的焦点。随着云计算、大数据、…...

DeepSeek 服务器繁忙的全面解决方案

目录 引文 正文 一、 服务器繁忙的原因分析 二、 解决方案 2.1切换网络 2.2使用网络加速工具 2.3错峰使用DeepSeek 2.4本地部署 2.5调用API 三、官方动态 一、技术研发与产品升级 二、市场合作与商业化进展 三、区域化布局与产业赋能 四、未来规划与社会责任 结语…...

将OpenWrt部署在x86服务器上

正文共&#xff1a;1234 字 40 图&#xff0c;预估阅读时间&#xff1a;2 分钟 如果你问ChatGPT有哪些开源的SD-WAN方案&#xff0c;他会这样答复你&#xff1a; 我们看到&#xff0c;OpenWrt也属于比较知名的开源SD-WAN解决方案。当然&#xff0c;在很久之前&#xff0c;我就发…...

计算机视觉:卷积神经网络(CNN)基本概念(一)

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络 一、引言 卷积神经网络&…...

企业文件共享中的权限管理与安全风险防范

在企业的日常运营中&#xff0c;文件共享是必不可少的一项工作。然而&#xff0c;文件共享过程中如果权限管理不当&#xff0c;极易引发安全风险&#xff0c;导致企业敏感信息泄露。因此&#xff0c;加强文件共享中的权限管理与安全风险防范&#xff0c;对于保障企业信息安全至…...

使用DeepSeek建立一个智能聊天机器人0.12

为了确保这段代码能够在Windows和Linux系统上都能正常运行,我考虑以下几个方面: 路径分隔符:在Windows和Linux中,文件路径的分隔符不同。Windows使用反斜杠(\),而Linux使用正斜杠(/)。我们可以使用 os.path.join 来处理路径,以确保跨平台兼容性。 消息框:tkinter.…...

国家队出手!DeepSeek上线国家超算互联网平台!

目前,国家超算互联网平台已推出 DeepSeek – R1 模型的 1.5B、7B、8B、14B 版本,后续还会在近期更新 32B、70B 等版本。 DeepSeek太火爆了!在这个春节档,直接成了全民热议的话题。 DeepSeek也毫无悬念地干到了全球增速最快的AI应用。这几天,国内的云计算厂家都在支持Dee…...

Deep seek学习日记1

Deepseek最强大的就是它的深度思考&#xff0c;并且展现了它的思考过程。 五种可使用Deep seek的方式&#xff08;应该不限于这五种&#xff0c;后续嵌入deepseek的应该更多&#xff0c;多了解一点因为官网容易崩~~&#xff09;&#xff1a; 1.deep seek官网 2.硅基流动silicon…...

乐理笔记(持续更新)

单音与音程 单音&#xff1a;由一个音组成。 音程&#xff1a;由两个音组成&#xff0c;表示两个音之间的音高距离。 如何数音程&#xff1a; 单音程&#xff1a;9 - X&#xff0c;性质相反。例如&#xff0c;9度音程减去某个数&#xff0c;性质会相反。 复音程&#xff1a…...

【动态路由】系统Web URL资源整合系列(后端技术实现)【nodejs实现】

需求说明 软件功能需求&#xff1a;反向代理功能&#xff08;描述&#xff1a;apollo、eureka控、apisix、sentinel、普米、kibana、timetask、grafana、hbase、skywalking-ui、pinpoint、cmak界面、kafka-map、nacos、gateway、elasticsearch、 oa-portal 业务应用等多个web资…...

PHP高效、轻量级表格数据处理库 OpenSpout ,很好用

OpenSpout 是一个高效、轻量级的 PHP 库&#xff0c;用于处理电子表格文件&#xff08;如 Excel 和 CSV&#xff09;。它支持读取和写入大型文件&#xff0c;且内存占用低。本文将详细介绍如何安装和使用 OpenSpout。 目录 安装 基本使用 高级功能 参考文档 安装 OpenSp…...

2010年上半年软件设计师考试上午真题的知识点整理(附真题及答案解析)

以下是2010年上半年软件设计师考试上午真题的知识点分类整理&#xff0c;涉及定义的详细解释&#xff0c;供背诵记忆。 1. 计算机组成原理 CPU与存储器的访问。 Cache的作用: 提高CPU访问主存数据的速度&#xff0c;减少访问延迟。存储器的层次结构: 包括寄存器、Cache、主存和…...

EventSource的使用

什么是EventSource EventSource 是一个用于服务器推送事件&#xff08;Server-Sent Events, SSE&#xff09;的接口&#xff0c;它允许服务器推送实时更新到浏览器。与 WebSocket 不同&#xff0c;SSE 是单向的&#xff08;服务器到客户端&#xff09;&#xff0c;适用于更新频…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

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

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

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...