【C++設計模式】組合模式

奮鬥的大慶發表於2020-12-04

1 含義

組合多個物件形成樹形結構以表示“部分-整體”的結構層次。組合模式對單個物件(葉子物件)和組合物件(容器物件)的使用具有一致性。

2 模式結構在這裡插入圖片描述

3 程式碼實現

舉例:假設你要開一家公司,要招募大量員工,當然有經理,主管,普通員工,相信再小的公司都會有這樣的組織架構。經理管主管,主管又管普通員工,普通員工自己管自己

#include<iostream>
#include<string>
#include<vector>

using namespace std;

//員工:抽象物件Component
class Employee
{
protected:
	string m_Name;
	string m_job;
public:
	Employee(string name,string job):m_Name(name),m_job(job){}
	virtual void add(Employee* subordinate) = 0;
	virtual void remove(Employee*subordinate) = 0;
	virtual void showMe()=0;
};


//設計員
class  Designer: public Employee
{
public:
	Designer(string name,string job):Employee(name,job){}
	 void add(Employee* subordinate) override
	{
		cout << "我是小員工,管理不了人!" << endl;
	}
	 void remove(Employee*subordinate)override
	{
		cout << "我是小員工,沒人歸我管理!" << endl;
	}

	void showMe()override
	{
		cout << "姓名:" << m_Name << "--" << "職位:" << m_job << endl;;
	}
};

//主管或經理:枝節點實現
class Manger :public Employee
{
private:
	vector<Employee*>m_Subordinates;
public:
	Manger(string name, string job) :Employee(name, job) {}
	void add(Employee* subordinate) override
	{
		m_Subordinates.push_back(subordinate);
	}

	void remove(Employee* subordinate) override
	{
		vector<Employee*>::iterator it = m_Subordinates.begin();
		while (it!=m_Subordinates.end())
		{
			if(*it==subordinate)
			{
				m_Subordinates.erase(it);
				delete subordinate;
				subordinate = nullptr;
				break;
			}
			it++;
		}
	}

	//顯示自己及手下
	void showMe()override
	{
		cout << "姓名:" << m_Name << "--" << "職位:" << m_job << endl;
		cout << m_Name << "手下有:";
		//顯示子節點
		vector<Employee*>::iterator it = m_Subordinates.begin();
		while (it != m_Subordinates.end())
		{
			(*it)->showMe();
			++it;
		}
	}
};


int main()
{
	//招收員工,從上到下
	Employee *manager = new Manger("小強", "經理");
	Employee *supervisor = new Manger("小明", "主管");
	Employee *supervisor1 = new Manger("小英", "主管");
	Employee *staff1 = new Designer("小李", "設計員");
	Employee *staff2 = new Designer("小王", "設計員");


	//組織公司架構
	manager->add(supervisor);
	manager->add(supervisor1);
	supervisor->add(staff1);
	supervisor1->add(staff2);

	manager->showMe();

	staff2->add(manager);



	return 0;
}

在這裡插入圖片描述

4 優缺點

優點:
利用多型和遞迴機制更方便地使用複雜樹結構。
缺點:
對於功能差異較大的類, 提供公共介面或許會有困難。 在特定情況下, 你需要過度一般化元件介面, 使其變得令人難以理解。

5 適用場景

需要實現樹狀物件結構, 可以使用組合模式

6.模式擴充套件

橋接模式、 狀態模式和策略模式 (在某種程度上包括介面卡模式) 模式的介面非常相似。 實際上, 它們都基於組合模式——即將工作委派給其他物件, 不過也各自解決了不同的問題。 模式並不只是以特定方式組織程式碼的配方, 你還可以使用它們來和其他開發者討論模式所解決的問題。

你可以在建立複雜組合樹時使用生成器模式, 因為這可使其構造步驟以遞迴的方式執行。

責任鏈模式通常和組合模式結合使用。 在這種情況下, 葉元件接收到請求後, 可以將請求沿包含全體父元件的鏈一直傳遞至物件樹的底部。

你可以使用迭代器模式來遍歷組合樹。

你可以使用訪問者模式對整個組合樹執行操作。

你可以使用享元模式實現組合樹的共享葉節點以節省記憶體。

組合和裝飾模式的結構圖很相似, 因為兩者都依賴遞迴組合來組織無限數量的物件。

裝飾類似於組合, 但其只有一個子元件。 此外還有一個明顯不同: 裝飾為被封裝物件新增了額外的職責, 組合僅對其子節點的結果進行了 “求和”。

但是, 模式也可以相互合作: 你可以使用裝飾來擴充套件組合樹中特定物件的行為。

大量使用組合和裝飾的設計通常可從對於原型模式的使用中獲益。 你可以通過該模式來複制複雜結構, 而非從零開始重新構造。

參考

1.https://refactoringguru.cn/design-patterns/composite
2.https://blog.csdn.net/a369189453/article/details/81193415
3.https://blog.csdn.net/lxq1997/article/details/89460373

相關文章