情景:在绘图编辑器和图形捕捉系统这样的图形应用程序中,我们需要使用简单的组件创建复杂的图标,用户可以组合多个简单组件以形成一些较大的组件,这些组件又可以组合成更大的组件。
分析:一个简单的实现方法是为Text和Line这样的图元定义一些类,另外定义一些类作为这些图元的容器。
问题:使用这些类的代码必须区别对待图元对象与容器对象,而实际上大多数情况下用户认为它们是一样的。对这些类区别使用,使得程序更为复杂。
解决方案:Composite模式描述了如何使用递归组合,使得用户不必对这些类进行区别
关键字:
Component(Graphic)--为组合中的对象声明接口,在适当的情况下实现所有类公共接口的缺省行为,声明一个接口用于访问和管理Component的子组件,(可选)在递归结构中定义一个接口,用于访问一个父部件,并在适当的情况下实现它
Leaf(Rectangle,Line,Text等)--在组合中表示叶节点对象,叶节点没有子节点,在组合中定义图元对象的行为
Composite(Picture)--定义有子部件的那些部件的行为,存储子部件,在Component接口中实现与子部件有关的操作
Client--通过Component接口操纵组合部件的对象
实现:
#include <list>
#include <iostream>
template<class Item>
class Iterator
{
public:
virtual void First() = 0;
virtual void Next() = 0;
virtual bool IsDone() const = 0;
virtual Item CurrentItem() const = 0;
protected:
Iterator();
};
class Graphic
{
public:
virtual ~Graphic();
const char *Name() { return m_strName; }
virtual void Draw();
virtual void Add(Graphic*);
virtual void Remove(Graphic*);
virtual Iterator<Graphic*>* CreateIterator();
protected:
Graphic(const char *);
private:
const char *m_strName;
};
class Line :public Graphic
{
public:
Line(const char *);
virtual ~Line();
virtual void Draw();
};
class Rectangle :public Graphic
{
public:
Rectangle(const char *);
virtual ~Rectangle();
virtual void Draw();
};
class Text :public Graphic
{
public:
Text(const char *);
virtual ~Text();
virtual void Draw();
};
class Picture :public Graphic
{
public:
virtual ~Picture();
Picture(const char *);
virtual void Draw();
virtual void Add(Graphic*);
virtual void Remove(Graphic*);
virtual Iterator<Graphic*>* CreateIterator();
private:
std::list<Graphic*> m_listGraphic;
};
void Picture::Draw()
{
Iterator<Graphic*>* it = CreateIterator();
for (it->First(); !it->IsDone(); it->Next())
{
it->CurrentItem()->Draw();
}
}
int main()
{
Line *line_1 = new Line("line_1");
Line *line_2 = new Line("line_2");
Rectangle *rectangle = new Rectangle("rectangle");
Text *text = new Text("text");
Picture *picture = new Picture("picture");
picture->Add(line_1);
picture->Add(line_2);
picture->Add(rectangle);
picture->Add(text);
picture->Draw();
return 0;
}
适用性:
- 你想表达对象的部分-整体层次结构。
- 你希望用户忽略组合对象与单个对象的不同,用户将统一使用组合结构中的所有对象。
应用:
几乎在所有的面向对象的系统中都有Composite模式的应用实例,如各大UI框架使用的Model/View/Controller就广泛使用了Composite模式。