为解决上一章的菜单中包含子菜单和菜单项的问题可以利用组合模式。
1. 组合模式包括三个基本类:组合,组件,叶子. 组合模式不仅能组合多个对象,并且能够是client不需要区分是组件还是叶子。组合和迭代器模式可以一起使用。
class Component
{
public:
virtual void Add(Component component) {};
virtual void Remove(Component component) {};
virtual Component GetChild(int i) {};
virtual void Print() {};
};
class Composite : public Component
{
public:
void Add(Component component);
void Remove(Component component);
Component GetChild(int i);
void Print();
public:
array<Component> m_components;
};
void Composite::Print()
{
Iterator *it = m_components.CreateIterator();
while(it->HasNext())
{
Component *pComponent = it->Next();
pComponent->Print();
}
}
class Leaf : public Component
{
public:
void Print();
};
void Leaf::Print()
{
// 创建迭代器遍历menuitem.
}
class Waiter
{
public:
Waiter(Component men)
: menus(men) {}
void Print()
{
menus->Print();
}
public:
Component menus;
};
client:
Component *pComp1 = new Menu();
Component *pComp2 = new Menu();
Component *pComp3 = new Menu();
Component allMenus;
allMenus.Add(pComp1);
allMenus.Add(pComp2);
allMenus.Add(pComp3);
Component *pItem1 = new MenuItem();
Component *pItem2 = new MenuItem();
Component *pMenu3 = new Menu();
pComp3->Add(pItem1);
pComp3->Add(pItem2);
pComp3->Add(pMenu3);
Waiter waiter(allMenus);
waiter.Print();
2.
更进一步
可以给Composite创建迭代器,使之可以遍历组件内的菜单项,而且子菜单也被包含进来。
Iterator *Composite::CreateIterator()
{
return new CompositeIterator(iterator);
}
Iterator *Leaf::CreateIterator()
{
return new NullIterator(); // 这里采用空对象,而不是空指针。HasNext()永远返回false.
} // 空对象好处是,不用判断返回是否为null.