组合模式(composite)主要用来解决树形层次结构对象模型。用统一的component对象屏蔽不同类型的子节点的差异。对于客户端来说都提供一个统一的接口。
典型应用场景如菜单,文件树等。
组合模式思想感觉跟递归有一些关系。将不同的items组合成一个composite,而不同的composite和叶子节点又能组合出新的composite。
看起来该模式似乎还比较简单。但是也没想到更多的场景。后面遇到再说吧。
写了个简单demo,可以描述一个文件系统:
/**
* @file test_composite.h
* @author itegel
* @date 2014/04/02 10:14:25
* @brief
*
**/
#ifndef __TEST_COMPOSITE_H_
#define __TEST_COMPOSITE_H_
#include <iostream>
#include <vector>
#include <string>
class Component{
public:
Component(){}
virtual void Add(Component * component) = 0;
virtual void Remove(Component * component) {
//do nothing for test
}
virtual void DisplayInfo() = 0;
};
class File : public Component{
public:
File(const char * name, int id){
name_ = name;
id_ = id;
}
virtual void Add(Component * component){
std::cout<<"File node cannot add sons!"<<std::endl;
//throw exception or do some exception handling here
}
virtual void DisplayInfo(){
std::cout<<name_<<"__"<<id_<<"__f"<<std::endl;
}
private:
std::string name_;
int id_;
};
class Directory : public Component{
public:
Directory(const char * name, int id){
name_ = name;
id_ = id;
}
virtual void Add(Component * component){
items_.push_back(component);
}
virtual void DisplayInfo(){
std::cout<<name_<<"__"<<id_<<"__d"<<std::endl;
std::vector<Component *>::iterator com_iter;
for (com_iter = items_.begin(); com_iter != items_.end(); com_iter++){
std::cout<<"\t";
(dynamic_cast<Component *>(*com_iter))->DisplayInfo();
}
}
private:
std::vector<Component * > items_;
std::string name_;
int id_;
};
#endif //__TEST_COMPOSITE_H_
/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
/**
* @file test_composit.cpp
* @author itege
* @date 2014/04/02 10:33:30
* @brief
*
**/
#include "test_composite.h"
int main(){
File f1("file1", 101);
Directory d1("dir1", 2001);
d1.Add(&f1);
File f2("file2", 201);
Directory d2("dir2", 3001);
d2.Add(&d1);
d2.Add(&f2);
std::cout<<"d2 info:"<<std::endl;
d2.DisplayInfo();
std::cout<<"d1 info:"<<std::endl;
d1.DisplayInfo();
}
输出
d2 info:
dir2__3001__d
dir1__2001__d
file1__101__f
file2__201__f
d1 info:
dir1__2001__d
file1__101__f
有个问题一直没高明白,望高人指点:
就是打印d2的时候,希望是其下面的子目录d1打印过程中也有缩进。
但是明显的d1下的f1打印的时候没有打印缩进。按理调用的应该是d1的DisplayInfo函数。
而d1打印时,其子节点应该是要先打印缩进之后才会打印的。一直没高明白。
后面有空再学习一下。