论接口的封装能力

简介: 论接口的封装能力

刚入职行业不到一年的菜鸟的心得体会,真实感受,不喜勿喷。

       为什么想到封装呢?还不是因为踩过坑,最近越来越感觉,直接用一些开源库很不方便,而且用起来总是忘塞。

       1.在工程开发过程中,我们不可避免的会用到其他人封住好的库。当然,作为程序员的基础素养之一,我们也得会封住一些好用的库,不仅仅是为了更好的迭代工程,更为了更好的使用一些开源库。

       2.说到开源库,最近蛮烦恼塞。因为刚入职从事程序员行业,这段时间一直在接触开源库还有一些开源框架。(我感觉看多了,开始习惯看源码了,之前都直接看博客。额,看不可的效果不可描述,总感觉很多时候看不明白,所以塞,不如看源码里的例子,遇到具体的点没明白的再去百度或者请教前辈。)

       3.最最重要的一点就是很多开源库为了支持更多的功能,在使用过程中会比较繁琐,并且很多时候我们只想使用一部分功能,通常我们会选择提前做一层封装。(自己封装的塞,肯定用得爽,虽然封住过程有点痛苦塞,长痛不如短痛塞)

封住一定要很规范

       个人觉得如果业务很简单,其实好用就行了,封装最初的目的也是为了好用。如果比较复杂的设计,比如好几个库杂糅在一起,而且之后会有功能扩展的需求,那么这个时候就得先考虑下,如何设计会比较好了。

       对于第一种情况,就不过多的描述了,很简单的。通常可以用C方式,也可以采用C++类的方式(看情况决定,为了自己方便)。

详细说下第二种情况

接口设计注意事项:

1.避免过度封装,过度封装会导致调bug很难理清楚逻辑,而且很不好维护

2.接口名称,通常使用驼峰规则就行,做到见名思意

3.参数尽量提炼,不要搞一堆没必要的参数,用起来很麻烦。无非必要,就不要

4.注释清晰,明了。不写注释是王八

接口设计的最佳效果

1.隔离用户操作与底层逻辑

(说人话,无非就是我给你这个接口就可以让你实现这个功能,不需要你去了解里面怎么玩的,想那么多干嘛,那是我封住接口的人需要考虑的塞)

接口封装的两种方法

1.PIMP(Pointer to Implementation)在接口类成员中包含一个指向实现类的指针,这样就可以最大限度的做到接口和实现进行分离的原则。

说白了,就是A实现了某种方法(类A不对外使用),而在A-inerface中声明一个A *pA,并且这套接口的方法内部就是调用了A的方法,有时候可能会做一些扩展,比如一个基础事件的集合,也就是有很多这样的事件

示例:

class A_interface

{

public:

       A_interface& operator+(const A_interface& com );

       A_interface& operator-(const A_interface& com );

       A_interface& operator*(const A_interface& com );

       A_interface& operator/(const A_interface& com );

private:

       A *p_A;

}

class A{

public:

       A& operator+(const A& com );

       A& operator-(const A& com );

       A& operator*(const A& com );

       A& operator/(const A& com );

private:

       double real_;

       double imaginary_;

};

===> 不可多说,这个方法反正我基本不用塞,自己体会塞

2.Object-Interface方法,采用c++继承多态,实现类继承接口类,功能接口定义成虚函数。

这个纯虚函数给你朋友用,其他部分搞成.so或者.dll (.lib\.a)

如果不满足塞,再来个管理类。说白了就一个工厂类塞,如果你觉得好玩,可以搞个反射塞。

//纯虚函数,接口成员函数

class Complex{

public:

   static std::unique_ptr<Complex> Create();    // 用来做工厂方法    

   virtual Complex& operator+(const Complex& com ) = 0;

   virtual Complex& operator-(const Complex& com )  = 0;

   virtual Complex& operator*(const Complex& com )  = 0;

   virtual Complex& operator/(const Complex& com )  = 0;

};

//Complex类功能的内部实现类

class ComplexImpl : public Complex{

public:

   virtual Complex& operator+(const Complex& com ) override;

   virtual Complex& operator-(const Complex& com ) override;

   virtual Complex& operator*(const Complex& com ) override;

   virtual Complex& operator/(const Complex& com ) override;

private:

   double real_;

   double imaginary_;

}

>>>将要暴露出去的接口都设置为纯虚函数,然后通过工厂模式Create获取不同基类的指针

std::unique_ptr<Complex> Complex::Create()

{

   return std::make_unique<ComplexImpl>();

}

>>>如此,我们完成将Complex类的实现细节全部封装隐藏起来了

>>>如果对于用户来说,是有必要获取实体的数据部分时,只需要添加响应的set和get方法

Object_interface抽象基类示例代码:

1.首先,声明一个接口 ---> 一般设置为纯虚函数

// circle.h

// 圆的接口类

class Circle {

public:

  virtual ~Circle() {};

  virtual double area() = 0;     // 接口方法:面积

};

2.通过继承的方式实现这个接口

// circle_impl.h

#include "circle.h"

 

// 圆的具体实现类

class CircleImpl : public Circle {

private:

   double radius;

public:

   CircleImpl(double radius);

   double area() override;

};

// circle_impl.cpp

#include <cmath>

#include "circle_impl.h"

 

inline double pi() {

   return std::atan(1) * 4;

};

 

CircleImpl::CircleImpl(double _radius) : radius(_radius) {

};

 

double CircleImpl::area() {

   return pi() * radius * radius;

};

3.最后,通过管理类创建接口派生类的实例,或者销毁接口派生类的实例

// circle_manager.h

#include "circle.h"

 

// 圆的创建工厂类

class CircleManager {

public:

   static Circle* create(double radius);     // 创建circle实例

   static void destroy(Circle* circlePtr);   // 销毁circle实例

};

// circle_manager.cpp

#include "circle_manager.h"

#include "circle_impl.h"

 

Circle* CircleManager::create(double radius) {

   Circle* circlePtr = new CircleImpl(radius);

 

   return circlePtr;

};

 

void CircleManager::destroy(Circle* circlePtr) {

   delete circlePtr;

};

// 使用示例

// main.cpp

#include <iostream>

#include "circle_manager.h"

#include "circle.h"

 

int main()

{

   Circle* circlePtr = CircleManager::create(3);

   cout << circlePtr->area() <<endl;

   CircleManager::destroy(circlePtr);

   

   system("pause");

 

   return 0;

}

 

相关文章
|
JSON 前端开发 安全
Apipost与Apifox对比,会选择谁?
Apipost与Apifox对比,其实两款软件都非常优秀。但从我的需求来说Apifox 似乎更满足我的需求,也更符合我的审美!
Apipost与Apifox对比,会选择谁?
|
Python
python、十六进制的颜色对照表
英文代码  形像颜色  HEX格式  RGB格式 LightPink 浅粉色 #FFB6C1 255,182,193 Pink 粉红 #FFC0CB 255,192,203 Crimson 猩红 #DC143C 220,20,60 LavenderBlush 脸红的淡紫色 #FFF0F5 255.
10588 0
python、十六进制的颜色对照表
|
6月前
|
SQL 运维 NoSQL
告别救火式运维!DAS Agent 助力企业迈入AI-Native数据库运维时代
阿里云瑶池DAS Agent是融合大模型与十万工单经验的智能数据库运维大脑,实现“发现-诊断-优化”全链路自治。支持云上/自建多引擎实例,秒级定位CPU飙升、死锁等根因,对话框内直接限流、SQL优化、死锁分析,7×24小时主动预防,助力企业迈入AI-Native运维时代。
539 1
|
2月前
|
运维 资源调度 监控
2026年客户健康度经营看板指南:续费风险、活跃回升与关键人覆盖字段设计
2026年,SaaS客户经营转向存量深耕,传统汇总式看板已失效。本文提出“客户健康度分层经营看板”新范式:聚焦续费风险预警、活跃回升真伪识别、关键人关系网络监控三大核心,打通CRM/产品/服务数据,统一字段口径与时间窗口,推动看板从“复盘工具”升级为支撑日常指挥的经营操作系统。
|
11月前
|
JavaScript 小程序 Java
基于微信小程序的线上博物馆系统
线上博物馆系统利用互联网与数字技术,实现文化遗产的数字化保护与传播,打破时空限制,推动文化传承与教育创新。结合Java、Vue及Uniapp等技术,构建跨平台、高互动的在线展览平台,提升公众文化体验。
|
4月前
|
存储 小程序 安全
如何为APP构建一个安全可控的沙箱运行环境,让第三方合作伙伴的小程序能够安全可控的运行在自己的APP里
如何为自己的APP引入一个安全可控的沙箱运行环境,沙箱为每个小程序创建一个独立的运行环境,实现第三方服务商通过小程序接入宿主APP,代码在自己可控的沙箱内运行,宿主APP通过管控后台掌握最终的决定权。
351 2
如何为APP构建一个安全可控的沙箱运行环境,让第三方合作伙伴的小程序能够安全可控的运行在自己的APP里
|
3月前
|
Web App开发 机器学习/深度学习 SQL
DeepSeek 怎么导出 Word?保存聊天记录、Markdown、公式的 5 种方法(2026 最新)
DeepSeek虽无官方Word导出功能,但用户已将其用作“第二文档助手”。本文详解5种导出方案:复制粘贴(简易)、Markdown转换(稳定)、Pandoc(专业)、在线工具(便捷)及DS随心转插件(全自动支持公式/表格/流程图)。适配学生、开发者与AI重度用户,助你高效交付高质量Word文档。
1088 0
|
4月前
|
JSON 人工智能 文字识别
飞书/钉钉/企微集成型办公Agent:实现一句话触发报销审批
本文介绍如何用AI办公Agent重构报销流程:员工群内一句话发起报销,Agent自动解析、验票、校验预算并推送审批,全程≤15分钟。涵盖多平台接入、大模型结构化提取、发票真伪核验及人工兜底机制,让财务专注高价值工作。(239字)
616 2
|
6月前
|
Web App开发 人工智能 自然语言处理
AI英语口语App
2026年AI英语口语App已迈入原生多模态实时交互时代:依托OpenAI Realtime API、Gemini Live等音频流原生引擎,实现&lt;500ms低延迟对话;融合音素级纠音、动态支架教学、RAG场景库、情感识别与离线轻量化模型,打造具备情感反馈与精准指导的“数字私教”。
|
5月前
|
边缘计算 监控 Serverless
基于 Serverless 与云边协同的 Mobile Agent 架构:侠客工坊技术解析
本文介绍“侠客工坊”提出的云边协同Mobile Agent架构,以解决云原生时代移动端执行断层问题:通过Serverless事件驱动调度、端侧轻量Vision-SLM视觉推理、全链路多模态可观测性及内核级零侵入输入,实现高可用、可监控、合规的移动智能自动化。
417 0