天天看點

大話設計模式19----組合模式大話設計模式

大話設計模式

1 組合模式(Composite)結構圖

大話設計模式19----組合模式大話設計模式

2 對組合模式的一些解釋

概念:将對象組合成樹形結構以表示“ 部分-整體”的層次結構。組合模式使得使用者對單個對象群組合對象的使用具有一緻性。如:Word文檔中對文字的處理,即可以處理單個字又可以處理多個字、甚至是對整個文檔的處理;再比如說總公司和各個分公司在職務功能都類似,但是子公司包含于總公司之中,如下圖的結構:

大話設計模式19----組合模式大話設計模式

Component類:

class Component
{
protected:
	string name;

public:
	Component(string name)
	{
		this->name = name;
	}

	//通過Add和Remove來實作增加樹葉或者樹枝的功能
	virtual void Add(Component *c){};
	virtual void Remove(Component *c){};

	virtual void Display(int depth){};
};
           

Leaf類:

class Leaf :public Component
{
public:
	Leaf(string name) :Component(name){}

	void Add(Component *c) override
	{
		cout << "葉子結點實作該接口的意義不大,因為葉子結點不會增加葉子或者樹枝,但是這麼做可以" ;
		cout << "消除葉子結點和樹枝結點對象在抽象層次的差別,使它們具有完全一緻的接口,這種方式稱之為透明方式" << endl;
	}

	void Remove(Component *c) override
	{
		cout << "同上" << endl;
	}

	void Display(int depth) override
	{
		cout << "顯示層次和名字" << endl;
	}
};
           

Composite類:

class  Composite :public Component
{
private:
	vector<Component> vec;//一個子對象集合用來存儲其下屬的樹枝節點和葉結點

public:
	Composite(string name) :Component(name){}

	void Add(Component *c) override
	{
		vec.push_back(c);
	}

	void Remove(Component *c) override
	{
		vec.Delete(c);//vector中沒有這種方法,這裡隻是形象的代表删除該葉結點或者枝節點
	}

	void Display(int depth) override
	{
		cout << "循環遞歸顯示該結點及其下屬結點" << endl;
	}
};
           

Client.h類

int main()
{
	Composite *root = new Composite("root");//生成根節點root,根上長出兩夜LeafA和LeafB
	root->Add(new Leaf("Leaf A"));
	root->Add(new Leaf("Leaf B"));

	Composite *comp = new Composite("Composite X");//跟上長出分支Composite X
	comp->Add(new Leaf("Leaf XA"));//該枝上長出兩個葉子結點
	comp->Add(new Leaf("Leaf XB"));

	root->Add(comp);

	.......依次類推;

	return 0;
}
           

Leaf(葉子)中也可以不實作Add和Remove方法,因為實作他們沒有意義,這種方式成為 安全方式,不過由于不透明,是以樹葉樹枝将不具有相同的接口,進而使得用戶端的調用就需要判斷一下;着這種角度來講,這種方式就不如 透明方式了。

使用場景:

  • 需求中展現部分與整體層次的結構的時候;
  • 希望使用者可以忽略組合對象與單個對象的不同,統一地使用組合結構中的所有對象時。

優點:

  • 組合模式定義了包含(人力資源部和财務部這些)基本對象和(分公司、辦事處等)組合對象的類層次結構。基本對象可以被組合成更複雜的組合對象,而這個組合對象又可以被組合,這樣不斷地遞歸下去,客戶代碼中,任何用到基本對象的地方都可以使用組合對象了;
  • 組合模式讓客戶可以一緻的使用組合結構和單個對象。

3 C++實作

3.1 代碼結構圖

大話設計模式19----組合模式大話設計模式

3.2 C++源代碼

公司類Component.h

#ifndef _Company_H_
#define _COMPONENT_H

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

using std::endl;
using std::cout;
using std::string;
using std::vector;

class Company
{
protected:
	string name;

public:
	Company(string name)
	{
		this->name = name;
	}

	virtual string getName(){ return name; }//傳回公司名字
	virtual void Add(Company *c){};//增加
	virtual void Remove(Company *c){};//移除
	virtual void Display(int depth){};//顯示
	virtual void LineOfDuty(){};//履行職責,不同的部門需要履行不同的職責
};

//建立具體的公司
class ConcreteCompany :public Company
{
private:
	vector<Company *> *vec;

public:
	ConcreteCompany(string name) :Company(name)
	{
		vec = new vector<Company *>();
	}

	//增加析構函數,防止記憶體洩漏
	~ConcreteCompany()
	{
		for (auto it = vec->begin(); it != vec->end(); ++it)
		{
			delete (*it);
		}

		delete vec;
	}

	string getName() override
	{
		return this->name;
	}

	//增加葉子結點
	void Add(Company *c) override
	{
		vec->push_back(c);
	}

	//删除葉子結點
	void Remove(Company *c) override
	{
		for (auto it = vec->begin(); it != vec->end(); ++it)
		{
			if (c->getName() == ((*it)->getName()))
			{
				vec->erase(it);
				break;
			}
		}
	}

	//列印
	void Display(int depth) override
	{
		for (int i = 0; i < depth; ++i)
			cout << "-";
		cout << name << endl;

		for (auto it = vec->begin(); it != vec->end(); ++it)
			(*it)->Display(depth + 4);
	}

	//職責
	void LineOfDuty() override
	{
		for (auto it = vec->begin(); it != vec->end(); ++it)
			(*it)->LineOfDuty();
	}
};

//人力資源部
class HRDepartment :public Company
{
public:
	HRDepartment(string name) :Company(name){}

	void Add(Company *c) override{}
	void Remove(Company *c) override{}
	void Display(int depth) override
	{
		for (int i = 0; i < depth; ++i)
			cout << "-";
		cout << name << endl;
	}

	void LineOfDuty() override
	{
		cout << name << " 負責招聘教育訓練管理" << endl;
	}

	string getName() override
	{
		return this->name;
	}
};

//财務部
class FinanceDepartment :public Company
{
public:
	FinanceDepartment(string name) :Company(name){}

	void Add(Company *c) override{}
	void Remove(Company *c) override{}
	void Display(int depth) override
	{
		for (int i = 0; i < depth; ++i)
			cout << "-";
		cout << name << endl;
	}

	void LineOfDuty() override
	{
		cout << name << " 公司财務收支管理" << endl;
	}

	string getName() override
	{
		return this->name;
	}
};
#endif
           

用戶端代碼:

#include"Component.h"

int main()
{
	ConcreteCompany *root = new ConcreteCompany("北京總公司");
	root->Add(new HRDepartment("總公司人力資源部"));
	root->Add(new FinanceDepartment("總公司财務部"));

	ConcreteCompany *comp = new ConcreteCompany("上海華東分公司");
	comp->Add(new HRDepartment("上海華東分公司人力資源部"));
	comp->Add(new FinanceDepartment("上海華東分公司财務部"));
	root->Add(comp);

	ConcreteCompany *comp2 = new ConcreteCompany("南京辦事處");
	comp2->Add(new HRDepartment("南京辦事處人力資源部"));
	comp2->Add(new FinanceDepartment("南京辦事處财務部"));
	comp->Add(comp2);

	ConcreteCompany *comp3 = new ConcreteCompany("杭州辦事處");
	comp3->Add(new HRDepartment("杭州辦事處人力資源部"));
	comp3->Add(new FinanceDepartment("杭州辦事處财務部"));
	comp->Add(comp3);

	cout << "結構圖" << endl;
	root->Display(1);
	cout << endl << endl;

	cout << "職責" << endl;
	root->LineOfDuty();
	cout << endl;

	delete root;//剩下的由析構函數自動釋放
	system("pause");
	return 0;
}
           

運作結果:

結構圖
-北京總公司
-----總公司人力資源部
-----總公司财務部
-----上海華東分公司
---------上海華東分公司人力資源部
---------上海華東分公司财務部
---------南京辦事處
-------------南京辦事處人力資源部
-------------南京辦事處财務部
---------杭州辦事處
-------------杭州辦事處人力資源部
-------------杭州辦事處财務部


職責
總公司人力資源部 負責招聘教育訓練管理
總公司财務部 公司财務收支管理
上海華東分公司人力資源部 負責招聘教育訓練管理
上海華東分公司财務部 公司财務收支管理
南京辦事處人力資源部 負責招聘教育訓練管理
南京辦事處财務部 公司财務收支管理
杭州辦事處人力資源部 負責招聘教育訓練管理
杭州辦事處财務部 公司财務收支管理

請按任意鍵繼續. . .
           

繼續閱讀