您的位置:首页 > 其它

23种设计模式之九(结构型模式)Composite模式

2015-02-03 14:41 323 查看


一、简介

Composite 组合模式解决的问题是:递归构建树状的组合结构以表示“部分-整体”的层次结构,用户不用关心到底是处理一个叶节点还是处理一个组合组件,可以一致地使用组合结构和单个对象。

Composite 组合模式的结构图为:



在Component中声明所有用来管理子对象的方法,其中包括Operation、Add、Remove和GetChild,这样实现Component接口的所有子类Composite都具备了Operation、Add、Remove和GetChild。好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备Add()、Remove()、GetChild()方法的功能,所以实现它是没有意义的。

二、详解

1、代码实现

(1)代码component.h:

#ifndef _COMPONENT_H_
#define _COMPONENT_H_

//Component抽象基类,为组合中的对象声明接口,声明了类共有接口的缺省行为(如这里的Add,Remove,GetChild函数)
class Component
{
	  public:
	  	  virtual ~Component();
	  public:
	  	  virtual void Operation() = 0;
	  	  virtual void Add(const Component &);
	  	  virtual void Remove(const Component &);
	  	  virtual Component *GetChild(int);
	  protected:
	  		Component();
	  private:	  
};

#endif
(2)代码component.cpp:

#include "component.h"

Component::Component()
{
}

Component::~Component()
{
}

void Component::Add(const Component &com)
{
}

void Component::Remove(const Component &com)
{
}

Component *Component::GetChild(int index)
{
}


(3)代码composite.h:

#ifndef _COMPOSITE_H_
#define _COMPOSITE_H_

#include <vector>
#include <iostream>
#include "component.h"
using namespace std;

//Composite:含有子组件的类
class Composite : public Component
{
	  public:
	  	  Composite();
	  	  ~Composite();
	  public:
	  	  //实现的接口
	  	  void Operation();
	  	  void Add(Component *com);
	  	  void Remove(Component *com);
	  	  Component *GetChild(int index);
	  protected:
	  private:
	  	  //这里采用vector来保存子组件
	  	  vector<Component *>comVec;
};

#endif
(4)代码composite.cpp:

#include "component.h"
#include "composite.h"

Composite::Composite()
{
}

Composite::~Composite()
{
}

void Composite::Operation()
{
	  cout<<"Composite Operation the vector"<<endl;
	  vector<Component *>::iterator comIter = comVec.begin();
	  for(;comIter != comVec.end(); comIter++) {
	      (*comIter)->Operation();
	  }
}

void Composite::Add(Component *com)
{
	  cout<<"Composite::Add..."<<endl;
	  comVec.push_back(com);
}

void Composite::Remove(Component *com)
{
}

Component *Composite::GetChild(int index)
{
	  cout<<"Composite::GetChild..."<<endl;
	  
	  if(index < 0 || index >= comVec.size()) {
         return NULL;
    }
	  
	  return comVec[index];
}
(5)代码leaf.h:

#ifndef _LEAF_H_
#define _LEAF_H_
#include "component.h"

//Leaf是叶子结点,也就是不含有子组件的结点类,所以不用实现Add、Remove、GetChild等方法
class Leaf : public Component
{
	  public:
	  	  Leaf();
	  	  ~Leaf();
	  	  //只实现Operation接口
	  	  void Operation();
	  protected:
	  private:
};

#endif


(6)代码leaf.cpp:

#include <iostream>
#include "leaf.h"
using namespace std;

Leaf::Leaf()
{
	  cout<<"---Leaf constructor"<<endl;
}

Leaf::~Leaf()
{
}

void Leaf::Operation()
{
	  cout<<"Leaf::Operation..."<<endl;
}


(7)代码main.cpp:

#include <iostream>
#include "component.h"
#include "composite.h"
#include "leaf.h"
using namespace std;

int main()
{
    //不管是叶子Leaf还是Composite对象pRoot、pCom都实现了Operation接口,所以可以一致对待,直接调用Operation()
    //体现了“使得用户对单个对象和组合对象的使用具有一致性”
	  Component *lf = new Leaf();
	  //执行叶子Operation操作
	  lf->Operation();
	  Component *lf2 = new Leaf();
	  
	  Composite *com = new Composite();
	  //组合对象添加叶子节点
	  com->Add(lf);
	  com->Add(lf2);
	  //执行组合对象Operation操作
	  com->Operation();
	  
	  //获取组合对象中的节点
	  Component *ll = com->GetChild(0);
	  ll->Operation();
	  
	  delete com;
	  delete lf;
	  delete lf2;
	  return 0;
}


(8)makefile:

CFLAGS = -g
DEFINED = #-D _VERSION
LIBS = 
CC = g++
INCLUDES = -I./
OBJS= main.o component.o composite.o leaf.o
TARGET= main
all:$(TARGET)

$(TARGET):$(OBJS)
	$(CC) $(CFLAGS) -o $@ $(OBJS)

.SUFFIXES:.o .h
.SUFFIXES:.cpp .o
.cpp.o:
	$(CC) $(DEFINED) -c $(CFLAGS) -o $@ $<

ok:
	./$(TARGET)
clean:
	rm -f $(OBJS) $(TARGET) core *.log


2、运行结果

(Centos6.3系统中运行结果:)




三、总结

(1)Composite 模式在实现中有一个问题就是要提供对于子节点(Leaf)的管理策略,这里使用的是 STL 中的 vector,也可以提供其他的实现方式,如数组、链表、Hash 表等。

(2)Composite 模式通过和 Decorator 模式有着类似的结构图,但是 Composite 模式旨在构造类,而 Decorator 模式重在不生成子类即可给对象添加职责。Decorator 模式重在修饰,而Composite 模式重在表示。

(3)源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/8419779)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: