为什么需要Composite设计模式?

如果客户代码过多地依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽象接口)的变化将引起客户端的频繁变化,带来了代码的维护性、扩展性等弊端。

什么是Composite设计模式?

常常有一些组件在内部具有特定的数据结构,如果让客户程序依赖这些特定的数据结构,将极大地破坏组件的复用。这时候,将这些特定数据结构封装在内部,在外部提供统一的接口,来实现与特定数据结构无关的访问,是一种行之有效的解决方案。

composite模式将特定的数据结构封装在内部,使得客户端可以无差别的访问对象,而不必关心对象内部复杂的实现结构。

Composite设计模式特点

Composite模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系转化为“一对一”的关系,使得客户代码可以一致地(复用)处理对象和对象容器,无需关系处理的是单个对象,还是组合的对象容器。

将对象组合成属性结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性(稳定)。

将客户代码与复杂的对象容器结构解耦是Composite的核心思想,解耦之后,客户代码将与存粹的抽象接口-----而非对象容器的内部实现结构----发生依赖,从而更能应对变化。

类图

面向对象设计模式学习笔记二Composite模式

蓝色部分固定不变,红色虚线可能变化;客户端程序关联稳定的虚接口component;leaf和composite继承实现了component接口;同时,composite聚合component(composite中有component的成员变量);

Code

//对外提供的统一接口
/***************虚接口***************/
class Component
{
public:
    virtual void process() = 0;
    virtual ~Component(){}
};
/***************虚接口***************/
//内部复杂数据结构
/*******************************************
通过组合多态对象,将复杂结构实现隐藏在内部,根据客
户端传入对象不同,实现多态调用。
对外提供统一的Component接口
*******************************************/
class Composite : public Component{//树节点
    
    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. process current node
        
/**************根据e(多态对象)的不同调用不同的process函数********************/       
        //2. process leaf nodes
        for (auto &e : elements)//多态递归调用
            e->process(); //(既可以调用Composite的process也可以调用Leaf的process)
/**************根据e(多态对象)的不同调用不同的process函数********************/       
    }
};

//叶子节点
class Leaf : public Component{
    string name;
public:
    Leaf(string s) : name(s) {}
            
    void process(){
        //process current node
    }
};
//客户端程序
/*************客户程序*************/
void Invoke(Component & c){//多态
    //...
    c.process();
    //...
}
/*************客户程序*************/

int main()
{

    Composite root("root");
    Composite treeNode1("treeNode1");
    Composite treeNode2("treeNode2");
    Composite treeNode3("treeNode3");
    Composite treeNode4("treeNode4");
    Leaf leat1("left1");
    Leaf leat2("left2");
    
    root.add(&treeNode1);
    treeNode1.add(&treeNode2);
    treeNode2.add(&leaf1);
    
    root.add(&treeNode3);
    treeNode3.add(&treeNode4);
    treeNode4.add(&leaf2);

    Invoke(root);//无差别访问
    Invoke(leaf2);//无差别访问
    Invoke(treeNode3)//无差别访问
/***************************
客户代码不用了解实现细节,通
过递归多态将将内部实现细节隐
藏起来。客户端不必了解内部复
杂结构。
****************************/
}

适用性

以下情况下适用Composite模式:
1.你想表示对象的部分-整体层次结构
2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

例子

1.

面向对象设计模式学习笔记二Composite模式

2.

面向对象设计模式学习笔记二Composite模式

 

相关文章:

  • 2021-09-01
  • 2021-10-29
  • 2021-09-22
  • 2022-12-23
  • 2022-12-23
  • 2021-06-02
猜你喜欢
  • 2022-01-09
  • 2022-02-22
  • 2021-09-09
  • 2021-08-05
  • 2022-01-05
  • 2021-08-13
  • 2022-12-23
相关资源
相似解决方案