常常在一些组件内部会有特定数据结构,如果客户代码直接使用这些特定数据结构,会极大破坏组件复用;因此,可以将组件中主句结构封装在内部,为外部提供统一的接口,来实现与特定数据结构无关的访问。
composite,iterator,chain of responsibility属于数据结构模式。
motivation:某些情况下,软件系统过多依赖对象容器复杂的内部实现,在其内部实现发生变化时,会对代码维护造成极大的麻烦;将客户代码与复杂的对象容器解耦;将对象组合成树形结构表示“部分-整体”层次结构,使得用户对单个对象和组合对象的使用具有一致性。
key interface or class:
1. component接口。
feature: composite子类和leaf子类。
structure:
template codes:
class Component{
pubic:
virtual void process()=0;
virtual ~Component(){}
};
//组合对象
class Composite: public Component{
private:
string name;
list<Component*> elements;
public:
Composite(const string& s):name(s){}
void add(Component* element){
elements.push_back(element);
}
void remove(Component* element){
elements.remove(element);
}
void process(){
//1.porcess current node
//2. process leaf nodes
for(auto &e:elements){
e->process(); //多态方法进行递归
}
}
}
//叶子对象,单一对象
class Leaf: public Component{
private:
string name;
public:
Composite(const string& s):name(s){}
void process(){
//porcess current node
}
}
void process(Component* c){
//...
c->process();
//...
}
int main(){
//建立符合对象
Composite root("root");
Composite treeNode1("treenode1");
Composite treeNode2("treenode2");
Composite treeNode3("treenode3");
Composite treeNode1("treenode1");
Leaf leaf1("leaf1");
Leaf leaf1("leaf1");
root.add(treeNode1);
treeNode1.add(treeNode2);
treeNode2.add(leaf1);
root.add(treeNode3);
treeNode3.add(treeNode4);
treeNode4.add(leaf2);
process(root);
process(leaf1); //对复合对象和单一对象的处理,调用一样的接口
}
summary:
1. composite采用树形结构来实现普遍存在的对象容器,将“一对多”的关系转换为“一对一”关系,使得客户代码可以一致性地处理单一对象和符合对象,无需关心是单一对象还是复合对象;
2.将客户代码和对象日期解耦,是composite的核心思想;解耦后,客户代码将依赖于抽象的接口,而非具体对象容器的内部实现,从而能用对变化;
3.composite模式在具体实现中,可以让子对象对父对象实现反溯;当父对象有频繁的遍历操作时,可有采用缓存的技巧来改善效率。