问题提出:

我们做事一般都有一套完整的流程比如:脱衣服——洗澡——穿衣服,如果用户操作直接不脱衣服从洗澡开始,那么程序可能就会出问题,例如定义一个一般的类模拟推理过程:

//提出问题
class Infer{
public:bool load_model(const string& file){context_ = file;return true;}void forward(){printf("使用%s进行推理\n",context_.c_str());}void destroy(){context_.clear();}private:string context_;
};

如果创建完对象上来就直接推理(跳过了context_初始化步骤):

int main()
{Infer infer;//1. 如果直接对对象进行推理infer.forward();return 0;
}

此时返回:

此时还能正常运行,因为这里context_未初始化时为空string对象,如果是个未初始化的空指针,那么程序会异常。

因此按照一般思维步骤,需要在当前调用之前进行判断:

    void forward(){//异常逻辑if(context_.empty()){//说明模型没加载上//此时需要写异常情况处理的定义(可能会比较复杂繁琐)printf("模型没有加载\n");return;}//正常逻辑printf("使用%s进行推理\n",context_.c_str());}

为什么会出现异常逻辑呢,因为我们并没有显式说明不能这么操作(这里指未初始化直接推理),那么有两种解决方法,一种是频繁告诉用户不能怎么怎么操作(这种方法对用户不友好,异常逻辑会耗费大量的时间,且如果有部分异常处理没有写好会造成封装的不安全性,导致崩溃,也会造成使用的复杂度变高),二是仅仅开放正常逻辑应该有的操作接口(RAII(资源获取即初始化) + 接口模式(实现类和接口类分离的模式))。

RAII(资源获取即初始化):

例如例子中:

int main()
{//资源获取Infer infer;//资源初始化infer.load_model("a");return 0;
}

两个步骤分别对应了资源获取和资源初始化,RAII要做的就是将两步合为一步,通过共享指针来完成:

//RAII
//获取infer实例,即表示加载模型
//加载模型失败则表示资源获取失败
//加载模型成功则表示资源获取成功
shared_ptr<Infer> create_infer(const string& file){shared_ptr<Infer> instance(new Infer());//如果load_model失败则instance为空指针if(!instance->load_model(file)){instance.reset();}return instance;
}

此时infer实例通过create_infer来完成,得到的instance不为空则说明获取资源成功且同时完成了模型加载工作,如果instance为空,则说明获取资源失败,简化了后续forward等的判断流程,可以删掉是否只加载了一次模型以及是否加载了模型等的异常逻辑判断:

int main()
{// //资源获取// Infer infer;// //资源初始化// infer.load_model("a");auto infer = create_infer("a");//只需要简单的是否为空指针的判断if(infer == nullptr){printf("failed");return -1;}infer->forward();return 0;
}

进一步和接口的配合可以实现模型只在create_infer中完成,且只完成一次,我们通过一个接口类InferInterface来实现接口类和定义类的分离,我们只希望暴露给用户forward函数:

//接口类是一个纯虚类
//只暴露调用者需要的函数,其他一律不暴露
//例如load_model通过RAII做了定义,属于不需要的范畴
//内部如果有启动线程等等,start,stop,也不需要暴露
class InferInterface{
public:virtual void forward() = 0;};

将Infer类作为InferInterface的派生类并重写forward函数:

class Infer : public InferInterface{
public:bool load_model(const string& file){context_ = file;return true;}virtual void forward() override{//正常逻辑printf("使用%s进行推理\n",context_.c_str());}void destroy(){context_.clear();}private:string context_;
};

在RAII中将返回类型改为接口类对象:

shared_ptr<InferInterface> create_infer(const string& file){shared_ptr<Infer> instance(new Infer());//如果load_model失败则instance为空指针if(!instance->load_model(file)){instance.reset();}return instance;
}

此时暴露给用户的只有forward函数。

RAII + 接口模式相关推荐

  1. Dell poweredge r210进BIOS修改磁盘控制器(SATA Controller)接口模式

    Dell poweredge r210进BIOS修改磁盘控制器(SATA Controller)接口模式 开机后按F2键进入BIOS设置,如下图: BIOS设置主界面: 使用上下键移动光标到" ...

  2. 装饰者模式-继承模式和接口模式

    接口模式: 基本接口定义: package com.example.designpatten.decoratormode.interfacemode;public interface Gun {pub ...

  3. 某大型银行深化系统技术方案之十三:服务层之服务接口模式

    传送门☞Android兵器谱☞转载请注明☞http://blog.csdn.net/leverage_1229 服务层 服务层主要体现了SOA体系下的组件复用和业务复用机制.服务的边界定义决定于粒度和 ...

  4. STM32:配置定时器为PWM输出模式以及编码器接口模式

    一:STM32的高级定时器TIM8配置为PWM输出模式 最近在工程项目中,需要用stm32的定时器 (以高级定时器TIM8为例 ) 产生两路PWM输出,作为电机的pwm输入,方法如下: /****** ...

  5. 交换机接口模式hybrid运用

    交换机接口模式hybrid运用 pvid:标签 untagged:针对端口的发送方从该端口出去的数据去除vlan标签 tagged:将指定的vlan标签数据经过交换机是无条件放行的一张表 hybrid ...

  6. VLAN和交换机接口模式:access、trunk、hybrid

    文章目录 1. 虚拟局域网:vlan 2. 交换机根据连接对象不同,接口模式: 2.1 access 2.2 trunk 2.3 Hybrid 1. 虚拟局域网:vlan vlan的好处/功能 1.划 ...

  7. 关于Cisco交换机接口模式的详细介绍

    cisco网络中,交换机在局域网中最终稳定状态的接口类型主要有四种:access/ trunk/ multi/ dot1q-tunnel. 1.access: 主要用来接入终端设备,如PC机.服务器. ...

  8. dhcp接口模式/全局模式

    一 接口模式 1.开始dhcp 服务 dhcp enable 2.进入接口 [XXXXXX0/0/0]dhcp select interface 设置dhcp租期 dhcp server lease ...

  9. 什么是DHCP(接口模式+全局模式)

    目录 一.DHCP原理 DHCP作用 地址池 DHCP报文类型 DHCP工作原理 DHCP租期更新 DHCP重绑定 IP地址释放 DHCP配置实验 实验要求 实验拓扑 实验配置步骤 总结 一.DHCP ...

最新文章

  1. 应用丨AI和机器学习如何改变美国政府决策方式
  2. 判断设备-安卓|苹果|微信
  3. C#装箱和拆箱(值类型和引用类型之间的转换)
  4. LeetCode114. 不同的路径 python实现
  5. (原创)c#学习笔记05--变量的更多内容01--类型转换01--隐式转换
  6. [2020-11-23 contest]图(dfs剪枝),劫富济贫(字典树),小A的树(树形DP),游戏(贪心/斜率优化)
  7. dbunit使用_使用dbUnit,JSON,HSQLDB和JUnit规则进行数据库单元测试
  8. python3动态加载模块的方法实现
  9. hive中创建表失败
  10. 相机模型与标定(三)--张正友标定
  11. grep正则表达式详解及练习
  12. Gitlab的使用(内含Git命令大全)
  13. 1136 mysql_MySQL错误:Error Code: 1136
  14. Mysql:数据库无法启动,系统找不到指定文件
  15. Windows-EFS加密文件
  16. 正确计算linux系统内存使用率
  17. python pptx库中文文档_基于python-pptx库中文文档及使用详解
  18. Cisco 动态路由(RIP协议)设计(含.pkt文件) 计算机网络课设/实验
  19. 新版微信不停跳转到小程序_微信小程序页面跳转 的几种方式
  20. Swing 写的日期时间组件

热门文章

  1. Unity加载C语言32dll,Unity3d 载入 C++/CLI (托管方式c++) 的动态库(DLL)
  2. Android中背光系统架构
  3. 关于利用js创建按钮点击事件获取input值的问题
  4. CSS自动换行后缩进
  5. 日期和时间戳转换方式
  6. 23HTML5期末大作业:电影影视网站设计——电影介绍(11页) 学生HTML个人网页作业作品下载 个人电影影视网页设计制作 大学生个人电影影视网站作业模板 简单个人电影影视
  7. 耳朵财经要闻|民政部:利用区块链技术增强公益组织的透明度;香港区块链协会联合会长:区块链给企业带来新的沟通和融资模式...
  8. Windows10关机问题----只有“睡眠”、“更新并重启”、“更新并关机”,但是又不想更新,解决办法...
  9. c语言计算学生成绩的合格率,分享一个几年前刚学c的一个小项目。成绩的输入,查询,排序,插...
  10. shiro550反序列化漏洞分析