EMACS & 程序 编程点滴...

天下难事必作于易,天下大事必作于细

Lastupdated: 2010-01-26

软件架构技术

TOP接口与实现分离

首先来看看【接口与实现分离】有什么好处:
  • 减少内存使用: 如果每次发布源代码,每一份程序都要有一份二进制代码,这浪费了内存空间。
  • 避免DLL Hell问题: 解决不同dll版本引起的问题。
  • 实现了简单的运行时多态: 基于同一接口类可能有不同的实现(不同的dll),用户可以选择使用,无须重新编译。

组件技术既是利用了接口与实现分离。在明确接口的基础上,实现出扩展性,维护性强大的组件架构设计。通过这样的实现, 将软件设计中的可变性最大限度地局部化,从而应对变化的软件需求。同时,作为公司的技术资产可以方便地再利用,扩展。

TOPC++中实现接口与实现分离的方法

用C++实现接口与实现分离很方便: 具体接口类用抽象基类定义,由其继承得到具体的实现类。再在实现类的dll中引入一全局C函 数,在其内部创建实现类的实例,再将其扔出去。最后,用户调用该C函数,得到实现类的实例。

例如以下的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/********** interface.h **********/
// 接口定义

#define interface struct

interface IChap4_1
{
    virtual void FuncA(void) = 0;
};

interface IChap4_2
{
    virtual void FuncB(void) = 0;
};

// 创建组件对象实例
extern void CreateInstance(IChap4_1 **);
extern void CreateInstance(IChap4_2 **);

// 释放组件对象实例
extern void Release(IChap4_1 *);
extern void Release(IChap4_2 *);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/********** component.cpp **********/
// 具体实现类
class Chap4 : public IChap4_1, public IChap4_2
{
    virtual void FuncA(void);
    virtual void FuncB(void);
};

void Chap4::FuncA(void)
{
    cout << "Chap4::FuncA~" << endl;
}

void Chap4::FuncB(void)
{
    cout << "Chap4::FuncB~" << endl;
}

extern void CreateInstance(IChap4_1 **pIFace)
{
    Chap4   *pChap4 = new Chap4;
    *pIFace = (IChap4_1 *)pChap4;
    cout << "CreateInstance IChap4_1~" << endl;
}

extern void CreateInstance(IChap4_2 **pIFace)
{
    Chap4   *pChap4 = new Chap4;
    *pIFace = (IChap4_2 *)pChap4;
    cout << "CreateInstance IChap4_2~" << endl;
}

extern void Release(IChap4_1 *pIFace)
{
    delete (Chap4 *)pIFace;
    cout << "Release IChap4_1~。" << endl;
}

extern void Release(IChap4_2 *pIFace)
{
    delete (Chap4 *)pIFace;
    cout << "Release IChap4_2~。" << endl;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/********** client.cpp **********/
#include <objbase.h>
#include <iostream.h>
#include "interface.h"

int main(void)
{
    IChap4_1    *pChap4_1;
    CreateInstance(&pChap4_1);
    pChap4_1->FuncA();
    Release(pChap4_1);

    IChap4_2    *pChap4_2;
    CreateInstance(&pChap4_2);
    pChap4_2->FuncB();
    Release(pChap4_2);
    return 0;
}

微软的COM既是利用这样的技术,只是为了通用,定义了许多接口(函数)。比如为了控制对象实例的生存周期和多重继承下的接 口查询,定义了IUnknown接口。其中AddRef(),Release()用来维护对象实例的引用计数,QueryInterface用来查询接口。 又比如为了各种语言间共享接口定义,用IDL来定义接口。为了跨语言环境创建件对象,定义了IClassFactory。等等。

TOP组件对象技术

TOP接口定义准则

要在已有的组件上重新定义,修改接口是不可能的,只能定义新的接口,让已有组件多重继承新的接口。所以,最初组件设计的时 候就要考虑其功能性,扩充性,维护性。以下从软件的凝聚度和结合度两方面讨论这个问题。
  • 凝聚度(cohesion,モジュール強度) : 模块,组件内功能间关联性的强度。

    包含了许多功能的模块,组件,或者函数,会使代码管理混乱。当用户的需求有所变化的时候,修改一处,影响的范围会变 得很大。所以说,凝聚度越高越好。凝聚度高的模块具有坚固性,信赖性,再利用性,易读性等特点。最好的情况下,一个功 能应对应一个模块(函数)。

  • 结合度(coupling) : 模块,组件间有调用关系接口之间的连结强度。

    结合度表征了模块独立性的强度。为了使模块更容易再利用,维护,模块间的结合度越低越好。

凝聚度和结合度就像是一个问题的两端。凝聚度高的模块,一般其结合度就低,而相反,凝聚度低的模块其结合度有很高。

一般按照下表来划分凝聚度的级别:

凝聚度 名称 特征
最强 功能凝聚 一个功能一个模块
连续凝聚 一个模块中虽然含有多个功能,但是分别单独被调用
协作凝聚
一般 顺序凝聚 将和某一数据相关的复数模块,按照顺序,组织成一个新的模块
临时凝聚
逻辑凝聚 一个模块中执行多个处理
最弱 共存凝聚 毫不相干的功能为了实现某一机能而组织在一个模块中

结合度的级别:

结合度 名称 特征
最低 数据结合 将对方的模块作为黑盒,只是将必要的数据作为参数来传递
标记结合 对方模块即使只使用结构体内的部分数据,也将构造体整体作为参数传递给对方
一般 控制结合 将模块控制代码作为参数传递给对方,从而控制对方模块的行为。于逻辑凝聚同等级别。
外部结合 模块间共用全局变量,通过全局变量实现模块间交互
最高 内容结合 须参照其他模块内部的构造来处理

http://www.ogis-ri.co.jp/otc/hiroba/technical/Cohesion_Coupling/Cohesion_Coupling.html

© www.yifeiyang.net
net tracking

                                                                                                 stats