【C++设计模式】组合模式

#ifndef __COMPOSITE_H__
#define __COMPOSITE_H__

#include <sstream>
#include <string>
#include <list>

//【说明】
// 组合模式的关键是定义了一个抽象构件类,它既可以代表叶子,又可以代表容器,而客户端针对该抽象构件类进行编程,无须知道它到底表示的是叶子还是容器,可以对其进行统一处理。
// 同时容器对象与抽象构件类之间还建立一个聚合关联关系,在容器对象中既可以包含叶子,也可以包含容器,以此实现递归组合,形成一个树形结构。

//【定义】
// 组合模式(Composite) :将对象组合成树形结构以表示“部分-整体”的层次结构,组合使得用户对单个对象和组合对象的使用具有一致性。

//【角色】
// Component(抽象构件):它可以是接口或抽象类,为叶子构件和容器构件对象声明接口。
// Leaf(叶子构件):它在组合结构中表示叶子节点对象,叶子节点没有子节点,它实现了抽象构件中定义的接口。
// Composite(容器构件):它在组合结构中表示容器节点对象,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点,它提供一个集合用于存储子节点。

//【意义】
//如果不使用组合模式,客户端代码将过多地依赖于容器对象复杂的内部实现结构,容器对象内部实现结构的变化将引起客户代码的频繁变化,带来了代码维护复杂、可扩展性差等弊端。
//组合模式通常可用来表示树形结构,这种结构随处可见,如公司里的部门结构,计算机里的目录结构等。

//【示例】

//目录条目,抽象出容器和内容的一致接口
class Entry
{
public:
	Entry(){ }

	virtual ~Entry(){ }

public:
	virtual std::string GetName() = 0;    

	virtual int GetSize() = 0;    

	virtual Entry * Add(Entry * entry); //不定义为纯虚函数,放在Entry里实现,则可以在File中不实现该方法

	virtual void PrintList(const std::string& prefix) = 0;
};

//文件
class File : public Entry
{
public:
	File(const std::string& name, int size) : m_name(name), m_size(size){ }

	~File(){ }

public:
	virtual std::string GetName();

	virtual int GetSize();

	virtual void PrintList(const std::string& prefix);

private:
	std::string m_name;
	int m_size;
};

//目录,维护一个目录条目列表
class Directoty : public Entry
{
public:
	Directoty(const std::string& name);

	~Directoty();

public:
	virtual std::string GetName();

	virtual int GetSize();

	virtual Entry * Add(Entry * entry);

	virtual void PrintList(const std::string& prefix);

private:
	std::string        m_name;
	std::list<Entry *> m_list;
};

void TestComposite();


#endif


#include "Composite.h"

Entry * Entry::Add(Entry * entry)
{
	return NULL;
}

std::string File::GetName()
{
	return m_name;
}

int File::GetSize()
{
	return m_size;
}

void File::PrintList(const std::string& prefix)
{
	printf("%s/%s \n", prefix.c_str(), m_name.c_str());
}

Directoty::Directoty(const std::string& name) : m_name(name)
{

}

Directoty::~Directoty()
{
	std::list<Entry *>::iterator iter = m_list.begin();
	for ( ; iter != m_list.end(); iter++)
	{
		if (*iter)
		{
			delete *iter;
			*iter = NULL;
		}
	}
}

std::string Directoty::GetName()
{
	return m_name;
}

int Directoty::GetSize()
{
	int size = 0;
	std::list<Entry *>::iterator iter = m_list.begin();
	for (; iter != m_list.end(); iter++)
	{
		Entry * entry = * iter;
		size += entry->GetSize();
	}
	return size;
}

Entry * Directoty::Add(Entry * entry)
{
	m_list.push_back(entry);
	return entry;
}

void Directoty::PrintList(const std::string& prefix)
{
	printf("%s/%s \n", prefix.c_str(), m_name.c_str());
	std::string newprefix = prefix + "/" + m_name;
	std::list<Entry *>::iterator iter = m_list.begin();
	for (; iter != m_list.end(); iter++)
	{
		Entry * entry = * iter;
		entry->PrintList(newprefix);
	}
}

void TestComposite()
{
	Entry * rootdir = new Directoty("root");
	Entry * bindir  = new Directoty("bin");
	Entry * usrdir  = new Directoty("usr");

	rootdir->Add(bindir);
	rootdir->Add(usrdir);

	bindir->Add(new File("vi",1000));
	bindir->Add(new File("ls",500));

	Entry * tom = new Directoty("Tom");
	usrdir->Add(tom);
	usrdir->Add(new File("mm.txt",123));

	tom->Add(new File("abc.txt",200));

	rootdir->PrintList("");

	delete rootdir;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值