分享
 
 
 

大卫的Design Patterns学习笔记08:Composite

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

一、概述

我们往往总是希望用一致的方式访问不同类型的对象,不论这个对象是同一类系中类型A的对象,还是类型B的对象,OO的多态性为我们提供了这种支持。

Composite模式将这种观点更进一步,当一个复杂对象由多个同一类系中的对象组成的时候,我们仍然希望用与访问单个对象一致的方式来访问该复杂对象(这其实仍是多态性在发挥作用,但在这个多态方法的内部处理使得我们可以做到“用一致的方法访问”这一点,见示例)。

Composite(组合)模式将对象组合成树形结构以表示“部分-整体”的层次结构,它使得客户对单个对象和复合对象的使用具有一致性。

二、结构

Composite模式的结构如下图所示:

图1:Composite模式类图示例

上述类图中的Leaf相当于数据结构Tree的叶子节点,而Composite相当于Tree的子节点。实际应用中,是否与上述类图一样,在基类Component中提供Add/Remove/GetChild等方法应视需求而定,因为有些情况下这些方法对于Leaf而言是没有意义的。

三、应用

以下情况使用Composite模式:

1、你想表示对象的部分-整体层次结构(这是基本的Composite的应用)。

2、你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象,在这些对象上执行某个操作(这才是Composite模式带给我们的好处)。

四、优缺点

Composite模式具有以下优缺点:

1、定义了包含基本对象和组合对象的类层次结构 基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断的递归下去。客户代码中,任何用到基本对象的地方都可以使用组合对象。

2、简化客户代码 客户可以一致地使用组合结构和单个对象。通常用户不知道(也不关心)处理的是一个叶节点还是一个组合组件。这就简化了客户代码,因为在定义组合的那些类中不需要写一些充斥着选择语句的函数。

3、使得更容易增加新类型的组件 新定义的Composite或Leaf子类自动地与已有的结构和客户代码一起工作,客户程序不需因新的Component类而改变。

4、使你的设计变得更加一般化 容易增加新组件也会产生一些问题,那就是很难限制组合中的组件。有时你希望一个组合只能有某些特定的组件。使用Composite时,你不能依赖类型系统施加这些约束,而必须在运行时刻进行检查。

五、举例

Java的AWT中的Component-Container体系是一个很好的Composite模式的例子。Container从Component派生,而Container中又可以包含有多个Component(甚至是Container,因为Container也是Component)。

但是,需要注意的是,是否能通过类似add的操作来添加被包容的对象,形成树状结构不是Composite模式的重点,Composite模式的重点在于,形成特定结构后,是否可以保证用统一的方法,在无需关心各被包容对象的前提下访问该对象,执行某个操作。

因此,虽然可以用Java的Collection构建多种容器类型的树状结构,这是一种Composite,但不是这里所讨论的Composite模式。虽然大家有相同的上层接口Collection,但是,各容器类缺少共同的“某个操作”。对于上面讲的AWT中的Component类系而言,“某个操作”可能是invalidate操作,或者是repaint操作。

在现代OS的文件系统实现中,往往不区分文件/目录,甚至设备,因为对于系统而言,他们没有太多的不同,在这里,目录就相当于类图中的Composite。下面是一个虚拟的目录管理的例子(真正的目录管理比这可复杂多了,具体可参考<Unix环境高级编程>):

#include <iostream>

#include <string>

#include <vector>

using namespace std;

class AbsFile {

public:

virtual void ls() = 0;

virtual ~AbsFile() { } // nothing to do in this demo.

protected:

string m_strName;

static int m_indent;

};

int AbsFile::m_indent = 0;

class File: public AbsFile {

public:

File( const char* name )

{

m_strName = name;

}

void ls()

{

for (int i=0; i < m_indent; i++)

cout << ' ';

cout << m_strName.c_str() << endl;

}

};

class Dir : public AbsFile {

public:

Dir( const char* name )

{

m_strName = name;

}

void add( AbsFile* f )

{

m_vFiles.push_back(f);

}

void remove(); // not implemented in this demo.

void ls() {

for (int i=0; i < m_indent; i++)

cout << ' ';

cout << m_strName << ":" << endl;

m_indent += 3;

vector<AbsFile*>::iterator it = m_vFiles.begin();

for (; it != m_vFiles.end(); it++)

(*it)->ls();

m_indent -= 3;

}

private:

vector<AbsFile*> m_vFiles;

};

void main( void )

{

Dir one("1"), two("2"), thr("3");

File a("a"), b("b"), c("c"), d("d"), e("e");

one.add( &a );

one.add( &two );

one.add( &b );

two.add( &c );

two.add( &d );

two.add( &thr );

thr.add( &e );

one.ls();

}

上述程序输出如下所示的树状文件结构:

1:

a

2:

c

d

3:

e

b

需要注意的是,上面的示例中采用的File(即类图中的Leaf)没有实现add操作,这并不是所有应用必须遵循的原则,视实际情况的需要,我们可以决定是否需要给File提供add等操作的实现。

参考:

1、http://home.earthlink.net/~huston2/dp/CompositeDemos.txt

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有