智能指针之设计模式3

这次我们看一下智能指针是如何使用策略模式来释放资源的,同时又是如何扩展功能,管理更多的资源对象类型的。

3、策略模式

策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的应用场景中,该行为有不同的实现算法。它的意图是:定义一系列算法,把它们一个个封装起来,并且使它们可相互替换,算法可独立于使用它的客户而变化。

下面是它的结构图:
在这里插入图片描述
组成结构:
—Strategy(抽象策略角色): 策略类,定义算法的公共接口。
—ConcreteStrategy(具体策略角色):具体策略类,实现某种具体算法。
—Context(环境上下文角色):持有一个策略类的引用,最终给客户端调用。

本质上就是在C++中,一个Strategy基类定义了虚函数(即算法),它的不同ConcreteStrategy派生类重写了虚函数的实现,而Context类中有一个Strategy引用类型的数据成员,可以存放不同的派生类对象,Context调用基类数据成员的虚函数时,并不知道数据成员的实际类型,显然这是面向对象动态绑定机制。因为是Context只依赖于Strategy基类类型,根据里氏替换原则,各个继承于Strategy的派生类ConcreteStrategy对象可以互相替换,不会对Context有任何影响。

我们看一下智能指针的删除器,它的功能是为智能指针提供释放资源的方法,有不同的形式和类型,智能指针会在它的reset()成员函数和析构函数中调用删除器,也不关心是什么形式的删除器,只要能调用它的void operator()(T *ptr)操作符就行。

我们再次脑洞大开一下,把一个提供了形如void operator()(T *ptr)调用操作符的函数对象类看作是策略基类,它定义了具体策略类所要实现的接口功能。如同上一篇文章中使用面向对象技术把指针封装成一个类一样,同样,现在也把删除器封装成一个函数对象类,作为抽象策略基类。如下所示:

class deleter {
public:void operator()(T *ptr);
}

该类对象的核心功能是:void operator()(T *ptr),等同于策略模式中的算法,供智能指针对象调用来销毁资源对象,只要一个类提供了参数是指针类型没有返回值的可调用操作符,都可以算作是它的派生类。

显然,对于普通函数:

void deleter_func(T *ptr) {delete ptr;
}

函数对象:

class deleter_func_obj {
public:void operator()(T *ptr) {delete ptr;}
}

lambda表达式:

auto deleter_lambda = [](T *ptr) {delete ptr};

以及function对象:

function<void(T *ptr)> func = bind(xxxx);

它们都提供了符合要求的可调用对象的函数接口,用面向对象术语的话,可以说它们都是deleter类的派生类,它们都被看作是具体的策略类对象,提供了不同的算法。那么在创建unique_ptr或者shared_ptr对象时,均可以选择一个作为参数传入,它们是可以互相替换的。显然,这正是策略模式背后所体现的思想,可以让智能指针灵活地支持多种类型的删除器,在这里,智能指针unique_ptr和shared_ptr对应了context环境角色,而删除器deleter对应了stragety策略角色。

这种模式的好处:

首先,可以使用不同形式的删除器。
显然,可以使用函数指针、函数对象、lambda表达式,以及function对象等不同形式来创建deleter对象,不管它们的外在形式如何,只要实现了void (T *ptr)方法,都可以在创建智能指针时选择一个作为策略对象传入,在需要的时候调用它们。

其次,可以扩展智能指针的功能。
策略模式中,可以把context角色类比为一个基类对象,而strategy角色就是派生类对象要实现的虚函数,只不过不是通过继承基类来实现虚函数功能,而是把要实现的虚函数封装成strategy对象,然后传入contex中去回调,显然这样也等同于使用不同的stragety扩展了context的不同功能。

我们知道,智能指针可以管理不同形式的资源,资源对象可以是数组,可以是普通对象、可以来自堆中,可以来自系统调用,在释放时,有的需要使用delete操作符,有的需要使用free()函数,有的需要使用close()函数。比如unique_ptr类,它是C++标准库提供的类型,无法修改它的源码,它是怎样做到能够管理更多的资源的?

看一下deleter角色,它的接口需要一个参数T *ptr,这个参数就是智能指针对象所管理的资源对象,在调用deleter时由智能指针作为参数传入ptr。因此,deleter知道ptr的类型信息,完全可以使用ptr做一些具体的算法逻辑操作,这就相当于扩展了智能指针对象的功能:只要deleter对象根据参数类型实现了不同的功能,智能指针又调用deleter,不就是等同于它通过deleter实现了该功能吗?可以脑补想象一下:智能指针类中有一个虚函数,它通过this指针来访问ptr数据成员,并实现了相关的功能。

传入不同的deleter对象,也等同于扩展了智能指针的不同功能。这样,智能指针不但可以管理内存资源,而且可以管理句柄、socket、文件指针、文件描述符等其它形式的资源。

下面一个演示,通过lambda表达式实现了关闭文件指针的操作,unique_ptr使用它扩展了自己的功能:也可以管理FILE文件指针资源了。

FILE *file = fopen("/tmp/tmp.txt", "r"); // 分配FILE资源
unique_ptr<FILE, void(*)(FILE *)> fup(file, [](FILE *file) {fclose(file);
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/80626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为盘古OS深度评测:构建AI自进化系统的实践密码

华为盘古OS通过分布式AI内核与自适应学习框架的深度耦合&#xff0c;重新定义操作系统级智能能力。实测显示其AI任务调度效率较传统系统提升17倍&#xff0c;本文从智能体编排、持续学习机制、端云协同架构三个维度&#xff0c;解析如何基于DevKit 3.0打造具备认知进化能力的下…

精益数据分析(28/126):解读商业模式拼图与关键指标

精益数据分析&#xff08;28/126&#xff09;&#xff1a;解读商业模式拼图与关键指标 在创业和数据分析的探索旅程中&#xff0c;每一次深入研究都可能带来新的启发和突破。今天&#xff0c;我们依旧带着共同进步的初心&#xff0c;深入解读《精益数据分析》中关于商业模式的…

GitLab Runner配置并行执行多个任务

检查并修改方法&#xff1a; 打开 Runner 的配置文件&#xff08;通常位于 /etc/gitlab-runner/config.toml 或 ~/.gitlab-runner/config.toml&#xff09;。 确保 concurrent 值大于 1&#xff0c;例如&#xff1a; concurrent 4 # 允许最多 4 个任务同时运行重启 Runner…

开发首个Spring Boot应用

&#x1f4cb; 前置条件 &#x1f3af; 在开始之前&#xff0c;请打开终端并运行以下命令以确保已安装正确版本的 Java&#xff1a; $ java -version openjdk version "17.0.4.1" 2022-08-12 LTS OpenJDK Runtime Environment (build 17.0.4.11-LTS) OpenJDK 64-Bi…

【信息系统项目管理师】高分论文:论质量管理和进度管理(智慧旅游平台建设项目)

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文1、规划质量管理2、质量保证3、质量控制论文 2019年3月,我作为项目经理,参加了某市智慧旅游平台建设项目,负责项目的全面管理, 该项目以打造一流的国内外生态旅游城市为目标,旨在大数据云平台建设的基…

DAM-3B,英伟达推出的多模态大语言模型

DAM-3B是什么 DAM-3B&#xff08;Describe Anything 3B&#xff09;是英伟达推出的一款多模态大语言模型&#xff0c;专门用于为图像和视频中的特定区域生成详细描述。用户可以通过点、边界框、涂鸦或掩码等方式来标识目标区域&#xff0c;从而得到精准且符合上下文的文本描述…

如何判断你的PyTorch是GPU版还是CPU版?

如何判断你的PyTorch是GPU版还是CPU版&#xff1f; PyTorch作为当前最流行的深度学习框架之一&#xff0c;支持在CPU和GPU(NVIDIA CUDA)上运行。对于深度学习开发者来说&#xff0c;正确识别PyTorch版本至关重要&#xff0c;因为GPU版本可以带来10-100倍的性能提升。本文将全面…

Gin框架

Gin 快速入门 go get -u github.com/gin-gonic/gin package main import gin "github.com/gin-gonic/gin"func main() {engine : gin.Default()engine.GET("/", func(c *gin.Context) {c.String(200, "Hello Gin")})engine.Run(":8888&q…

【Project】基于spark-App端口懂车帝数据采集与可视化

文章目录 hadoop完全分布式部署hdfs-site.xmlcore-site.xmlmarpred-site.xmlyarn-site.xml spark集群部署spark-env.sh mongodb分片模式部署config 服务器初始化config 副本集 shard 服务器初始化shard 副本集 mongos服务器添加shard设置chunk大小 启动分片为集合 user 创建索引…

brew 安装openjdk查看其版本

使用brew&#xff08;如果你使用Homebrew安装&#xff09; 如果你通过Homebrew安装了OpenJDK&#xff0c;可以使用以下命令来查看安装的版本,&#xff1a; brew list --versions openjdk8 这将会列出所有通过Homebrew安装的OpenJDK版本及其版本号。 3. 查看/usr/libexec/ja…

【Linux网络】构建与优化HTTP请求处理 - HttpRequest从理解到实现

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…

Day12(回溯法)——LeetCode51.N皇后39.组合总和

1 前言 今天刷了三道回溯法和一道每日推荐&#xff0c;三道回溯法也迷迷糊糊的&#xff0c;每日推荐把自己绕进去了&#xff0c;虽然是一道之前做过的题的变种。刷的脑子疼。。。今天挑两道回溯题写一下吧&#xff0c;其中有一道是之前做过的N皇后&#xff0c;今天在详细写一写…

初阶数据结构:二叉搜索树

目录 概念 性能 效率分析 二分缺陷 功能 插入 查找 删除 实现 应用 概念 二叉搜索树&#xff08;又称&#xff1a;二叉排序树&#xff09;&#xff0c;是由一些具有特别性质的二叉树衍变而来。 只要一棵二叉树具备以下性质&#xff0c;即可称作二叉搜索树。 【1】若…

详解springcloud gateway工作原理、断言、filter、uri、id、全局跨域、globalfilter等以及关键源码实现

1.gateway概念 网关就是当前微服务项目的"统一入口"程序中的网关就是当前微服务项目对外界开放的统一入口所有外界的请求都需要先经过网关才能访问到我们的程序提供了统一入口之后,方便对所有请求进行统一的检查和管理 2. 网关的主要功能 将所有请求统一经过网关网…

C#中的弱引用使用

弱引用&#xff08;Weak Reference&#xff09;是一种特殊的引用类型&#xff0c;它允许你引用一个对象&#xff0c;但不会阻止该对象被垃圾回收器&#xff08;GC&#xff09;回收。弱引用通常用于需要缓存或跟踪对象&#xff0c;但又不希望因保留引用而导致内存泄漏的场景。弱…

spring响应式编程系列:异步生产数据

目录 示例 大致流程 create new MonoCreate subscribe new LambdaMonoSubscriber monoCreate.subscribe accept success onNext 时序图 类图 数据发布者 MonoCreate 数据订阅者 LambdaMonoSubscriber 订阅的消息体 DefaultMonoSink 本篇文章我们来研究如何将…

MCP Python SDK构建的**SQLite浏览器**的完整操作指南

以下是使用MCP Python SDK构建的SQLite浏览器的完整操作指南&#xff1a; 一、环境准备 安装依赖 # 安装MCP SDK及SQLite支持 pip install mcp sqlite3创建测试数据库 sqlite3 test.db <<EOF CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT); IN…

【Python爬虫基础篇】--3.cookie和session

目录 1.cookie 1.1.定义 1.2.参数 1.3.分类 2.session 3.使用cookie登录微博 4.使用session登录 1.cookie 由于http是一个无状态的协议&#xff0c;请求与请求之间无法相互传递或者记录一些信息&#xff0c;cookie和session正是为了解决这个问题而产生。 例子&#xff1…

风车邮箱系统详细使用指南:Windows与Ubuntu双平台解析

风车邮箱系统V1.2使用手册 风车邮箱系统详细使用指南&#xff1a;Windows与Ubuntu双平台解析 前言 在日常网络活动中&#xff0c;我们经常需要一个临时邮箱来注册各类网站或接收验证码&#xff0c;但不想使用自己的真实邮箱。「风车无线邮箱系统」作为一款优秀的临时邮箱工具…

同样的接口用postman/apifox能跑通,用jmeter跑就报错500

之前没用过jmeter,第一次用调试压测脚本遇到了问题 一样的接口用postman能跑通&#xff0c;用jmeter跑就报错500&#xff0c;百度很多文章都说是该接口需要加一个‘内容编码’改成utf-8,我加了还是不行 后来我就想到apifox好像有隐藏的header&#xff0c;然后开始比较apifox的…