Composite模式

意图:将对象组合成树形结构表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

动机: 软件在某些情况下,客户代码过多的依赖于对象容器复杂的内部实现结构,对象容器内部结构(而非抽象接口)的变换将引起客户代码的频繁变化,带来了代码的维护性,扩展性等弊端。

适用性:

1. 你想表示对象的部分-整体层次结构

2. 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中所有的对象。

结构:

参与者

Component:为组合中的对象声明接口;在适当的情况下,实现所有类共有接口的缺省行为;声明一个接口用户访问和管理Component的子组件;在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。

Leaf: 在组合中表示叶结点对象,叶结点没有子结点;在组合中定义对象的行为。

Composite: 定义有子部件的那些部件的行为;存储子部件;在Component接口中实现与子部件有关的操作。

Client:通过component接口操纵组合部件对象

协作

用户使用Component类接口与组合结构中的对象进行交互,如果接受者是叶结点,则直接处理请求;如果接受者是Composite,它通常将请求转发给它的子部件。

效果

1. 定义了包含基本对象和组合对象的类层次结构

2. 简化客户代码

3. 使得更容易增加新类型的组件

4. 使设计更加一般化

实现:

代码示例如下:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
class Component{
public:
  virtual ~Component(){}
  virtual void Process() = 0;
  virtual void Add(Component *){}
  virtual void Remove(Component *){}
  Component *getChild(int){ return nullptr;}

protected:
  Component(){}
  Component(const std::string& name): _name(name){}
  std::string _name;
};

class Composite : public Component{
public:
  Composite(){}
  Composite(const std::string& name):Component(name){}
  ~Composite(){}
  void Process(){
    std::cout << "name : " << _name << std::endl;
    for (auto c : _component) {
      c->Process();
    }
  }
  void Add(Component *c){
    _component.emplace_back(c);
  }
  void Remove(Component *c){
    auto it = std::find(_component.begin(),_component.end(),c);
    if (it != _component.end()){
      Component *temp = *it;
        _component.erase(it);
        delete temp;
        temp = nullptr;
    }
  }
  Component *getChild(int index){
    if (index < 0 || index > _component.size()){
      return nullptr;
    }
    return _component[index];
  }
private:
  std::vector<Component *> _component;
};
class Leaf : public Component{
public:
  Leaf(){}
  Leaf(std::string const& name) :Component(name){}
  ~Leaf(){}

  void Process(){
    std::cout << "I am " << _name << std::endl;
  }
};
int main(int argc,char *argv[])
{
  Composite* root = new Composite("root");
  Composite* leftTree = new Composite("left tree");
  Composite* rightTree = new Composite("right tree");

  Leaf *leaf1 = new Leaf("left leaf 1");
  Leaf *leaf2 = new Leaf("right leaf 2");
  Leaf *leaf3 = new Leaf("left leaf 3");
  Leaf *leaf4 = new Leaf("right leaf 4");
  leftTree->Add(leaf1);
  leftTree->Add(leaf2);

  rightTree->Add(leaf3);
  rightTree->Add(leaf4);
  root->Add(leftTree);
  root->Add(rightTree);

  root->Process();

  leftTree->Remove(leaf1);
  leftTree->Remove(leaf2);
  rightTree->Remove(leaf3);
  rightTree->Remove(leaf4);
  root->Remove(rightTree);
  root->Remove(leftTree);
  delete root;
  return 0;
}

发布于 2020-11-26 15:17