软件设计的核心:
通过设计稳定的接口,分隔系统各部分(上下层次:上层应用逻辑/底层核心支撑框架;平行的层次:模型/视图/控制器),让各部分独立的变化。
接口在软件设计中至关重要,设计良好,稳定可靠,高内聚低耦合,可扩展性强的接口能保证软件稳定的进展升级。

软件架构其实就是接口的设计。

设计模式的核心思想:
1.分析系统中经常变化的和稳定的部分

2.设计接口分隔上面两部分
3.通过添加一个中间层封装接口,可以实现任何设计需求

各种不同的设计模式其实就是在不同的需求下,围绕上面三点的不同表现形式。

一个中间层就是封装了一个设计概念。

[设计模式中的例子...]


看看中间层如何在COM中起作用。
1.智能指针
客户使用COM往往在复制接口指针后需要手动调用AddRef,使用完后调用Release。
这一工作使得COM使用非常麻烦。
另外QueryInterface中的void**参数也不是类型安全的。

这一切可以通过智能接口指针简化编程。
智能接口指针就是简化设计的一个中间层。

2. 调度接口, IDispatch
C++可以直接通过COM接口访问COM组件,因为它可以直接访问vbtl
C++客户 <==> COM接口(vbtl) <==> COM组件
那么VB,javascript等客户呢?他们不能直接访问内存,访问vbtl
这时加入一个中间层 IDispatch,然后这样
VB客户 <==> IDispatch::Invoke <==> 调度接口(vbtl) <==> 实现IDispatch接口的COM组件
中间层 IDispatch 接口对VB的请求作了vbtl映射,分隔了两边的变化


3.类型库
通过调度接口IDispatch,VB,C++用户可以在不知COM接口任何信息情况下调用COM组件。
VB用户 ==(直接使用,编译器无法检查参数类型) ==> COM组件
但这样做不在编译时进行类型检查,容易引入错误(bug)。
类型库提供COM组件接口信息,它类似于C++头文件,但是二进制的,语言无关的。
VB用户 ==(类型库,编译器检查参数类型) ==> COM组件
这里,类型库就是中间层,提供编译时类型检查功能


中间层在Windows系统中的应用
1.创建线程
操作系统提供CreateThread创建线程,这个函数是底层的,独立于语言的,任何语言的创建线程函数最终应该都是调用了CreateThread。
对于C++,创建线程有特殊的要求,不能直接调用CreateThread。
C++标准库中很多函数,如strerror, asctime等未考虑多线程,使用了全局的变量,所以再多线程下运行时库会创建_ptidata的数据结构
与每个线程关联。
为分隔两部分,C++提供_beginthreadex创建线程。
C++用户 <==> _beginthreadex <==> CreateThread
_beginthreadex相当于中间层,分隔系统部分和用户部分

2.RAII
C++异常机制保证局部变量的析构函数被调用。
可通过C++对象生命期来控制资源
例如CPPUnit中有一段代码:


[cpp]  view plain copy


1. static CPPUNIT_NS::TestSuite *suite()                                      /  
2.     {                                                                          /  
3. const CPPUNIT_NS::TestNamer &namer = getTestNamer__();                   /  
4.       std::auto_ptr<CPPUNIT_NS::TestSuite> suite(                              /  
5. new CPPUNIT_NS::TestSuite( namer.getFixtureName() ));             /  
6.       CPPUNIT_NS::ConcretTestFixtureFactory<TestFixtureType> factory;          /  
7.       CPPUNIT_NS::TestSuiteBuilderContextBase context( *suite.get(),           /  
8.                                                        namer,                  /  
9.                                                        factory );              /  
10.       TestFixtureType::addTestsToSuite( context );                             /  
11. return suite.release();                                                  /  
12.     }


[cpp]  view plain copy


1. static CPPUNIT_NS::TestSuite *suite()                                      /  
2.     {                                                                          /  
3. const CPPUNIT_NS::TestNamer &namer = getTestNamer__();                   /  
4.       std::auto_ptr<CPPUNIT_NS::TestSuite> suite(                              /  
5. new CPPUNIT_NS::TestSuite( namer.getFixtureName() ));             /  
6.       CPPUNIT_NS::ConcretTestFixtureFactory<TestFixtureType> factory;          /  
7.       CPPUNIT_NS::TestSuiteBuilderContextBase context( *suite.get(),           /  
8.                                                        namer,                  /  
9.                                                        factory );              /  
10.       TestFixtureType::addTestsToSuite( context );                             /  
11. return suite.release();                                                  /  
12.     }


  


这里通过std::auto_ptr 智能指针确保在发生异常情况下在堆上开辟的 CPPUNIT_NS::TestSuite 对象能被正确释放。


std::auto_ptr 相当于用户和编译器之间的一个中间层,辅助内存管理。