C++设计模式11-组合模式----靠着大树好乘凉

定义

 

(GoF《设计模式》):将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

组成

① Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。

② Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。

③ Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。

适用性

 

以下情况下适用Composite模式:

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

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

 

例子

我们每天在公司上班,我们的公司其实就是一个树型结构的,最上边是总公司,总公司下面还有很多子公司而每个子公司有很很多部门。这样整个大公司就是一颗大树,每个子公司同时也是一颗小叔

首先是公司的抽象接口

// 公司抽象类 
class Company
{
public :
    Company(std::string name)
    :m_name(name)
    {
    }

    virtual ~Company( )
    {

    }

    virtual void Add(Company *pCompany)        // 增加子公司
    {

    }

    virtual void Show(int depth) = 0;               // 显示部门
protected :
    std::string m_name;                         // 显示公司名字

};


其次是公司的实现

// 公司类 
class ConcreteCompany : public Company
{
public :
    ConcreteCompany(std::string name)
    :Company(name)
    {

    }

    virtual ~ConcreteCompany( ){ };         // 虚析构函数

    void Add(Company *company)     // 添加子公司
	{
		this->m_companyList.push_back(company);        // 将子公司或者部门加入到公司的列表中
	}

    void Show(int depth)               // 显示公司部门
	{
		for(int pos = 0; pos < depth; pos++)
		{
			std::cout <<"-";
		}
		std::cout <<this->m_name <<std::endl;
		for(std::list<Company *>::iterator it = this->m_companyList.begin( );
			it != this->m_companyList.end( );
			++it)
		{
            (*it)->Show(depth + 2);
		}
	}

protected :
    std::list<Company *> m_companyList;          // 下属公司列表
};


接着是财务部门的实现

// 财务部门 
class FinaceDepartment : public Company
{
public :
    FinaceDepartment(std::string name)
    :Company(name)
    {

    }

    virtual ~FinaceDepartment( )
    {
    }

	void Show(int depth)               // 显示公司部门
	{
		for(int pos = 0; pos < depth; pos++)
		{
			std::cout <<"-";
		}
		std::cout <<this->m_name <<std::endl;
	}
};


然后是人力资源部门

// 人力部门 
class HRDepartment : public Company
{
public :
    HRDepartment(std::string name)
    :Company(name)
    {
    }

    virtual ~HRDepartment( ){ };         // 虚析构函数


	void Show(int depth)               // 显示公司部门
	{
		for(int pos = 0; pos < depth; pos++)
		{
			std::cout <<"-";
		}
		std::cout <<this->m_name <<std::endl;
	}

};


最后是客户端代码

int main()
{
    // 总公司
    Company *root = new ConcreteCompany("总公司");

    Company *rootHR = new HRDepartment("人力资源部");
    Company *rootFI = new FinaceDepartment("财务部");
    root->Add(rootHR);
    root->Add(rootFI);

    // 分公司A
    Company *left = new ConcreteCompany("分公司A");
    Company *leftHR = new HRDepartment("分公司A人力资源部");
    Company *leftFI = new FinaceDepartment("分公司A财务部");
    left->Add(leftHR);
    left->Add(leftFI);
    root->Add(left);

    // 分公司B
    Company *right = new ConcreteCompany("分公司B");
    Company *righHR = new HRDepartment("分公司B人力资源部");
    Company *righFI = new FinaceDepartment("分公司B财务部");
    right->Add(righHR);
    right->Add(righFI);
    root->Add(right);


    root->Show(0);


    return 0;
}


总结

 

组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以像处理简单元素一样来处理复杂元素。

如果你想要创建层次结构,并可以在其中以相同的方式对待所有元素,那么组合模式就是最理想的选择。本章使用了一个文件系统的例子来举例说明了组合模式的用途。在这个例子中,文件和目录都执行相同的接口,这是组合模式的关键。通过执行相同的接口,你就可以用相同的方式对待文件和目录,从而实现将文件或者目录储存为目录的子级元素。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值