大話設計模式
1 組合模式(Composite)結構圖
2 對組合模式的一些解釋
概念:将對象組合成樹形結構以表示“ 部分-整體”的層次結構。組合模式使得使用者對單個對象群組合對象的使用具有一緻性。如:Word文檔中對文字的處理,即可以處理單個字又可以處理多個字、甚至是對整個文檔的處理;再比如說總公司和各個分公司在職務功能都類似,但是子公司包含于總公司之中,如下圖的結構:
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 代碼結構圖
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;
}
運作結果:
結構圖
-北京總公司
-----總公司人力資源部
-----總公司财務部
-----上海華東分公司
---------上海華東分公司人力資源部
---------上海華東分公司财務部
---------南京辦事處
-------------南京辦事處人力資源部
-------------南京辦事處财務部
---------杭州辦事處
-------------杭州辦事處人力資源部
-------------杭州辦事處财務部
職責
總公司人力資源部 負責招聘教育訓練管理
總公司财務部 公司财務收支管理
上海華東分公司人力資源部 負責招聘教育訓練管理
上海華東分公司财務部 公司财務收支管理
南京辦事處人力資源部 負責招聘教育訓練管理
南京辦事處财務部 公司财務收支管理
杭州辦事處人力資源部 負責招聘教育訓練管理
杭州辦事處财務部 公司财務收支管理
請按任意鍵繼續. . .