PIMPL设计模式的理解和使用
以下两段不同程序的比较
//file a.h
#include "a.h"
#include “ b.h”
class A{
void Fun();
B b;
}
//file:a.cpp
#include "a.h" //无形中也引入了b.h
void A::fun(){
b.fun();//调用类a的fun方法
}
//file: main.cpp
#include"a.h." //无形中也引入了b.h
int main(){
A a;
a.fun();
return 0;
}
由以上代码可以观察到:
1、引入了更多的头文件,降低了编译的速度
main.cpp 和a.cpp中无形中引入了b.h
2、提高了模块的耦合度
a.编译器
b.运行期
假如B类做了改变B类的大小改变了,a.cpp也需要重新编译,重新分配空间.那么也就是A类依赖与B类的实现。
假如B类有子类,则在运行期中不能使用多态的功能,也就是B类在此前情况不能被其子类更换。那么这样就提高了模块的耦合度
3、降低了接口的稳定程度
a、对于库的使用,方法不能改变
b、对于库的编译,动态库的变更,客户程序也需要重新编译
意思是:把a.h和a.cpp编译成动态库,mai.cpp当作客户程序。如何动态库改变,客户程序也需要重新编译。类A发生改变了,main.cpp也需要重新编译。客户程序不仅仅依赖于接口还依赖与类A了。
出现的以上问题可以用PIMPL思想来解决。
PIMPL(private implementation或pointer to implementation)也称为handle/body idiom
PIML背后的思想是把客户与所有关于类的私有部分的知识隔离开。避免其它类知道其内部结构
可利用指针来解决:
1、降低编译依赖、提高重编译速度
a、因为指针对于32为的系统来说大小是4,64的系统来说是大小是8,这是相对稳定的。
b、即使类B发生改变,指针的大小也不会发生改变。文件a.h也不需要重编译
c、利用指针以后a.h不需要包含b.h,只需要进行前向声明。
d、main.cpp包含了a.h但a.h中没有包含b.h,不依赖于b.h
e、假如类B有子类,可以在在运行期间通过指针调用B类的子类,进行调用实现多态的功能。
2、接口和实现分离
通过使用指针,其所指的类的实现进行分离了,不关心类B的实现,指针的大小是固定的。
3、降低模块的耦合度
a.编译期
main.cpp包含了a.h但a.h中没有包含b.h,不依赖于b.h
b.运行期
假如类B有子类,可以在在运行期间通过指针调用B类的子类,进行调用实现多态的功能。
4、提高了接口的稳定程度
a、对于库的使用,方法不能改变
b、对于库的编译,动态库的变更,客户程序不用重新编译
如果把a.h和a.cpp编译成动态库,mai.cpp当作客户程序,假如类B发生改变但是其指针大小并没改变,库也没有改变,所以客户程序不用重新编译。那么在软件升级的过程中,只需要升级动态库即可,客户程序不需要改变。
该指针也可以是智能指针,那么智能指针所持有的对象发生改变,那么智能指针的大小也不会发生改变,其大小或是4或是8
// file a.h
class B;//前向声明
class A {
public:
A(){}
~A(){}
void Fun();
B* b_;
};
// file a.cpp
#include "a.h"
#include “b.h"//b.h只需要包含一次
A::A() : px_( new A ) {
}
A::~A() {
delete b_;
b_ = 0;
}
void A::Fun {
b_->Fun();
}
// file main.cpp
#include “a.h” //没有包含b.h
int main(void)
{
A a;
a.Fun();
}
PIMPL设计模式的理解和使用的更多相关文章
- 【设计模式+原型理解】第一章:使用Javascript来巧妙实现经典的设计模式
刚开始学习设计模式之前,我是没想说要学习设计模式的,我只是因为想学习JS中的原型prototype知识,一开始我想JS中为什么要存在原型这个东西?于是慢慢通过原型而接触到设计模式,后来发现我这个过程是 ...
- MVC和MVVM设计模式简单理解
1.mvc设计模式理解 Model: 模型 持有所有的数据状态和业务逻辑; 泛指数据库,链接数据库,建立数据模型 View: 视图 用来展示数据模型在页面上,泛指前端 Controller: 控制器, ...
- java 23种设计模式 深入理解
以下是学习过程中查询的资料,别人总结的资料,比较容易理解(站在各位巨人的肩膀上,望博主勿究) 创建型抽象工厂模式 http://www.cnblogs.com/java-my-life/archive ...
- java 23种设计模式 深入理解【转】
以下是学习过程中查询的资料,别人总结的资料,比较容易理解(站在各位巨人的肩膀上,望博主勿究) 创建型抽象工厂模式 http://www.cnblogs.com/java-my-life/archive ...
- DAO设计模式的理解
为了降低耦合性,提出了DAO封装数据库操作的设计模式. 它可以实现业务逻辑与数据库访问相分离.相对来说,数据库是比较稳定的,其中DAO组件依赖于数据库系统,提供数据库访问的接口. 一般的DAO的封装由 ...
- 设计模式 --深入理解javascript
/* 一.单例模式 */ var Universe; (function () { var instance; Universe = function Universe() { if (instanc ...
- 【设计模式+原型理解】第三章:javascript五种继承父类方式
[前言] 我们都知道,面向对象(类)的三大特征:封装.继承.多态 继承:子类继承父类的私有属性和公有方法 封装:把相同的代码写在一个函数中 多态: ->重载:JS严格意义上是没有重载,但可以通过 ...
- JavaScript设计模式的简单理解
设计模式可以理解为一系列的代码框架,我觉得主要涉及封装的概念.把实现某一功能的代码段封装在函数中,可以方便调用,同时利于代码的复用,提高了代码的可维护性.下面简单介绍一下几种设计模式的个人感受. 1. ...
- 深入理解javascript之设计模式
设计模式 设计模式是命名.抽象和识别对可重用的面向对象设计实用的的通用设计结构. 设计模式确定类和他们的实体.他们的角色和协作.还有他们的责任分配. 每个设计模式都聚焦于一个面向对象的设计难题或问题. ...
随机推荐
- SQL Server 索引的自动维护 <第十三篇>
在有大量事务的数据库中,表和索引随着时间的推移而碎片化.因此,为了增进性能,应该定期检查表和索引的碎片,并对具有大量碎片的进行整理. 1.确定当前数据库中所有需要分析碎片的表. 2.确定所有表和索引的 ...
- SQL数据转移
方法一:如果想把数据库A中的表Table1中的数据复制到数据库B中的表Table2中,也就是要预先建立Table2,可以使用一下语句: use B goinsert into Table2 selec ...
- C语言随笔_return答疑
1. 例子,看实例2-2.这道题有同学会问,那个return有什么用?这么讲吧,return是个英文单词,中文意思是“返回”,用在程序里也是返回的意思,返回啥呢?返回一个值.在func函数中,retu ...
- 百度地图LV1.5实践项目开发工具类bmap.util.jsV1.3
/** * 百度地图使用工具类-v1.5 * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email b ...
- 剑指offer-面试题10:二进制中1的个数
题目:请实现一个函数,输入一个函数,输出该数二进制表示中1的个数.例如把9 表示成二进制是1001,有2位是1.因此如果输入9,该函数输出2. 这道题最典型的方法就是用移位统计,就比如统计9的二进制1 ...
- tr转换或删除字符
字符处理命令:tr —— 转换或删除字符 逐个字符处理而不是处理单词的tr [OPTION]... SET1 [SET2] -d: 删除出现在字符集中的所有字符 tr ab AB
- Impala 2、Impala Shell 和 Impala SQL
1.Impala 外部 Shell Impala外部Shell 就是不进入Impala内部,直接执行的ImpalaShell 例如通过外部Shell查看Impala帮助可以使用: $ impala-s ...
- activity之栈管理
在android中.一个activity组件能够激活还有一个activity组件:本程序activity和其他程序的activity. 若新的被激活的activity组件属于还有一个应用程序, ...
- idea maven jetty插件热部署
maven tomcat插件好像无法进行热部署,jetty可以如下配置实现热部署,但是idea无法进行自动编译,所以需要如下快捷键 Ctrl+Shift+F9,编译 Ctrl+F9,生成项目 < ...
- webconfig 初认识
本文摘自网络大神们,还有待补充. -------------------------------------------------------------------- .net 提供的是针对当前机 ...