设计模式---组合模式

48 阅读2分钟

定义

组合模式(Composite Pattern)是一种结构型设计模式,它将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

结构

  • Component(抽象组件) :为组合对象中的对象声明接口,实现默认行为,可以是接口或抽象类。

  • Leaf(叶子节点) :叶子节点是组合中最基本的组成部分,它没有子节点。

  • Composite(复合节点) :复合节点是有子节点的节点,它实现了 Component 接口,并且存储子节点,定义与子节点有关的行为。

优点

  • 定义了包含叶子对象和组合对象的类层次结构:用户可以一致地使用组合对象和单个对象。

  • 简化客户端代码:客户代码可以一致地处理单个对象和组合对象,而不需要关心它们的区别。

  • 更容易增加新的类型:可以通过扩展叶子节点或组合节点来添加新类型,无需修改现有代码。

代码示例

公司管理系统

#include <iostream>
#include <vector>

// 公司抽象类
class Company
{
protected:
	std::string name;

public:
	explicit Company(const std::string& name) : name(name) {}
	virtual void add(std::shared_ptr<Company> company) = 0;		// 增加
	virtual void remove(std::shared_ptr<Company> company) = 0;	// 移除
	virtual void display(int depth) const = 0;					// 显示

	virtual void lineOfDuty() const = 0;						// 履行职责
};


// 具体分公司类,树枝节点
class ConcreteCompany : public Company
{
protected:
	std::vector<std::shared_ptr<Company>> children;

public:
	explicit ConcreteCompany(const std::string& name) : Company(name) {}
	
	void add(std::shared_ptr<Company> company) override
	{
		children.push_back(company);
	}

	void remove(std::shared_ptr<Company> company) override
	{
		children.erase(std::remove(children.begin(), children.end(), company), children.end());
	}

	void display(int depth) const override
	{
		std::string indent(depth, '-');
		std::cout << indent << name << std::endl;
		for (const auto& child : children)
		{
			child->display(depth + 2);
		}
	}

	void lineOfDuty() const override
	{
		for (const auto& child : children)
		{
			child->lineOfDuty();
		}
	}
};


// 部门类,树叶节点
class Department : public Company
{
public:
	explicit Department(const std::string& name) : Company(name) {}

	void add(std::shared_ptr<Company> company) override
	{
		throw std::runtime_error("Cannot add to a department");
	}

	void remove(std::shared_ptr<Company> company) override
	{
		throw std::runtime_error("Cannot remove from a department");
	}

	void display(int depth) const override
	{
		std::string indent(depth, '-');
		std::cout << indent << name << std::endl;
	}

	void lineOfDuty() const override
	{
		std::cout << name << " : Performing duties" << std::endl;
	}
};


int main()
{
	std::shared_ptr<Company> root = std::make_shared<ConcreteCompany>("Head Office");
	std::shared_ptr<Company> branch1 = std::make_shared<ConcreteCompany>("Branch Office 1");
	std::shared_ptr<Company> branch2 = std::make_shared<ConcreteCompany>("Branch Office 2");

	root->add(branch1);
	root->add(branch2);

	std::shared_ptr<Company> dept1 = std::make_shared<Department>("HR Department");
	std::shared_ptr<Company> dept2 = std::make_shared<Department>("Finance Department");

	branch1->add(dept1);
	branch2->add(dept2);

	std::cout << "Company Structure: " << std::endl;
	root->display(1);

	std::cout << "\nLine of Duty: " << std::endl;
	root->lineOfDuty();


	system("pause");
	return 0;
}

image.png

应用场景

  • 希望表示对象的部分-整体层次结构。

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