组合模式:
将对象组合成树形结构来表示部分与整体的关系。组合模式让客户能将单个对象和组合对象统一对待。
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
感觉这是一个很有意思的模式,递归的思路在这里面也得到了体现。如果考虑的业务模型中存在树形结构可以考虑这个模式。
UML图:
主要包括:
- Component(DrawingElement):为组合模式中的对象声明了一个接口;实现了一些缺省的行为;声明了一些访问子对象的接口。
- Leaf(PrimitiveElement):代表组合模式中的叶节点。叶节点不再包含其它节点。
- Composite(CompositeElement):定义有组合对象的行为;包含其它组合对象;实现了对子对象操作的一些接口。
C++代码实现如下:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Component
{
public:
Component(string n=string("")):name(n)
{
}
virtual void add(Component * c)
{
}
virtual void removeComponent(Component * c)
{
}
virtual Component* getChild(int index)
{
}
virtual void display(int depth)=0;
protected:
string name;
};
class Leaf:public Component
{
public:
Leaf(string str=""):Component(str)
{
}
void display(int depth)
{
string str(depth+2,‘-‘);
std::cout<<str<<name<<std::endl;
}
};
class Composite:public Component
{
public:
Composite(string str=""):Component(str)
{
}
void add(Component* c)
{
children.push_back(c);
}
void removeComponent(Component *c)
{
children.erase( remove(children.begin(),children.end(),c),children.end());
}
void display(int depth)
{
string str(depth+2,‘-‘);
std::cout<<str<<name<<std::endl;
vector<Component*>::iterator iter=children.begin();
for(;iter!=children.end();iter++)
(*iter)->display(depth+1);
}
Component* getChild(int index)
{
return children[index];
}
private:
vector<Component *> children;
};
int main()
{
std::cout<<"组合模式例子"<<std::endl;
Component *root=new Composite("root");
Component * etc=new Composite("etc");
Component * mnt=new Composite("mnt");
root->add(etc);
root->add(mnt);
Component * txt1=new Leaf("txt1");
Component *txt2=new Leaf("txt2");
etc->add(txt1);
etc->add(txt2);
root->display(0);
std::cout<<std::endl<<std::endl<<"after erase"<<std::endl;
etc->removeComponent(txt1);
root->display(0);
return 0;
}
这里也复习了一下stl容器删除操作。如果提供的是指针,直接进行erase即可,但是如果要删除具有特定值的对象,可以按照下列规则:
对于在内存中连续的顺序容器,如vector,deque,string推荐erase-remove的方法(这种方法对list也可用,但是list有更高效的方法)
vector<int> c;
//注意remove是<algorithm>中的函数
c.erase( remove(c.begin(),c.end(), 25), c.end());
对于list而言,可以使用list的成员函数remove,这样效率会更高一些:
list<int> list_int;
....
list_int.remove(25);
对于关联容器,可以直接调用erase函数
map<int, int> mapContainer;
...
mapContainer.erase(25);
执行输出:
下面是一个具体的绘图程序的例子:
- Component为DrawingElement,为绘图元素
- Leaf为PrimitiveElement,基本的绘图元素,不能再包含其它绘图元素
- Composite为CompositeElement
实际上上面的结构是UI中各种元素的简化版,UI中存在各种基本元素,比如按钮,文本框,也包括组合元素,比如各种布局控件,对话框等。它们应该是组合模式一个很好的应用。
UML类图:
C++实现代码:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class DarawingElement
{
public:
DarawingElement(string n=string("")):name(n)
{
}
virtual void add(DarawingElement * c)
{
}
virtual void removeDarawingElement(DarawingElement * c)
{
}
virtual DarawingElement* getChild(int index)
{
}
virtual void display(int depth)=0;
protected:
string name;
};
class PrimitiveElement:public DarawingElement
{
public:
PrimitiveElement(string str=""):DarawingElement(str)
{
}
void display(int depth)
{
string str(depth+2,‘-‘);
std::cout<<str<<name<<std::endl;
}
};
class CompositeElement:public DarawingElement
{
public:
CompositeElement(string str=""):DarawingElement(str)
{
}
void add(DarawingElement* c)
{
children.push_back(c);
}
void removeElement(DarawingElement *c)
{
children.erase( remove(children.begin(),children.end(),c),children.end());
}
void display(int depth)
{
string str(depth+2,‘-‘);
std::cout<<str<<"+"<<name<<std::endl;
vector<DarawingElement*>::iterator iter=children.begin();
for(;iter!=children.end();iter++)
(*iter)->display(depth+1);
}
private:
vector<DarawingElement *> children;
};
int main()
{
std::cout<<"具体的组合模式,画图程序例子"<<std::endl;
DarawingElement *pic=new CompositeElement("picture");
DarawingElement * redLine=new PrimitiveElement("red line");
DarawingElement * blueCircle=new PrimitiveElement("blueCircle");
DarawingElement * greenBox=new PrimitiveElement("green box");
pic->add(redLine);
pic->add(blueCircle);
pic->add(greenBox);
DarawingElement * twoCircles=new CompositeElement("two circles");
DarawingElement * blackCircle=new PrimitiveElement("black circle");
DarawingElement * whiteCircle=new PrimitiveElement("white Circle");
twoCircles->add(blackCircle);
twoCircles->add(whiteCircle);
pic->add(twoCircles);
pic->display(1);
return 0;
}
执行输出:
时间: 2024-10-11 23:49:53