定义
将对象组合成树形结构以表示“部分-
整体”的层次结构。组合(Composite
)模式使得用户对单个对象和组合对象的使用具有一致性。
结构
理解
1. Component
是组合对象的基类,定义了类的公共方法;提供一个访问和管理子组件的方法。
管理子组件的方法:Add-
添加子组件;Remove-
移除子组件;GetChild-
遍历获取组建对象的指针。
Operation
是需要子组件具体定义的公共接口。
2. Leaf
是组合对象的叶子节点(树叶)。叶子节点没有子组件(也就没有管理子组件的方法),只有公共行为方法Operation
。
3. Composite
是具体的子组件类(树枝)。实现基类接口。它可以继续派生子组件或者叶子节点。
4. Client
通过Component
基类来操作组合对象。
要点
1.
组合模式提供了一种解决对象之间递归组合的解决办法。组合对象包含两种派生类:包含子组件的树枝(Composite
)和叶子组件的树叶(Leaf
)。这样组合对象就可以继续组合对象,形成复杂的组合对象应用。
2.
最大化组合对象基类Component
。客户是不知道具体对象调用的是Leaf
还是Composite
。为了达到这个目的,基类Component
的方法就要最大化,并且提供默认实现,Leaf
和Composite
根据实际情况来重新实现。
应用
1.
多级菜单的实现可以使用组合模式。
2.
著名的开源测试框架XUnit
(JUnit
、CppUnit
)系列,就是使用Composite
模式,更多可以参考:
http://junit.sourceforge.net/doc/cookstour/cookstour.htm
源码中模拟XUnit
,使用Composite
实现测试框架。
源码
#include
<iostream>
#include
<set>
#include
<string>
using
namespace std;
//
组合对象基类
Component
class
CTestComponent
{
public
:
CTestComponent() {};
CTestComponent(const string &strName) : m_strName(strName){};
virtual ~CTestComponent() {};
//
测试工作方法。相当于模式的
Operation
virtual void RunTest() {};
//
增加一个测试组件
virtual void Add(CTestComponent* p) {cout << "add" << endl;};
//
移除一个测试组件
virtual void Remove(CTestComponent* p) {};
//
测试用例名称
string m_strName;
};
//
组合对象子组件
Composite
class
CTestComposite : public CTestComponent
{
public
:
CTestComposite() {};
CTestComposite(const string &strName) : CTestComponent(strName)
{};
virtual ~CTestComposite() {};
virtual void RunTest()
{
for (SetTestComponentItr itr = m_setComponent.begin(); itr != m_setComponent.end(); itr++)
{
cout << "run test name: " << (*itr)->m_strName << endl;
(*itr)->RunTest();
}
};
virtual void Add(CTestComponent* p) {
cout << "add test name: " << p->m_strName << endl;
m_setComponent.insert(p);
};
virtual void Remove(CTestComponent* p) {
cout << "remove test name: " << p->m_strName << endl;
m_setComponent.erase(p);
};
protected
:
set<CTestComponent*> m_setComponent;
typedef set<CTestComponent*> SetTestComponent;
typedef set<CTestComponent*>::iterator SetTestComponentItr;
};
//
应用模式
/
#define
TEST_RESULT(a, b) /
{ /
if ((a) == (b)) { /
cout << " test (" << a << ", " << b << ") reuslt: TRUE" << endl; /
} /
else { /
cout << " test (" << a << ", " << b << ") reuslt: FALSE" << endl; /
/
} /
} /
class
CTestCasePlus : public CTestComposite
{
public
:
CTestCasePlus(const string &strName) : CTestComposite(strName)
{};
int Plus(const int a, const int b) {
return a + b;
}
void RunTest()
{
int i = Plus(1, 2);
cout << " test: "<< i << " == (1 + 2)" << endl;
TEST_RESULT(i, 3);
}
};
class
CTestCaseSubtract : public CTestComposite
{
public
:
CTestCaseSubtract(const string &strName) : CTestComposite(strName)
{};
int Subtract(const int a, const int b) {
//return a – b;
return b – a; //error
}
void RunTest()
{
int i = Subtract(1, 2);
cout << " test: "<< i << " == (1 – 2)" << endl;
TEST_RESULT(i, -1);
}
};
int
main()
{
CTestCasePlus testCase1("TestCasePlus");
CTestCaseSubtract testCase2("TestCaseSubtract");
//Client
调用
CTestComposite composite;
composite.Add(&testCase1);
composite.Add(&testCase2);
composite.RunTest();
composite.Remove(&testCase1);
composite.Remove(&testCase2);
system("pause");
return 0;
}
输出:
add test name: TestCasePlus
add test name: TestCaseSubtract
run test name: TestCaseSubtract
test: 1 == (1 – 2)
test (1, -1) reuslt: FALSE
run test name: TestCasePlus
test: 3 == (1 + 2)
test (3, 3) reuslt: TRUE
remove test name: TestCasePlus
remove test name: TestCaseSubtract
转载本站文章请注明,转载自:神秘果
本文链接: http://www.shenmiguo.com/archives/2009/303_design-patterns-composite.html