コンポジットパターンは、
・要素の集合を表現するオブジェクト
・その集合に含まれる要素を表現するオブジェクト
を一様に扱えるようなデザインパターンです。
適用前
まず、皆さんがやるとしたら下記の様にクラスを用意しませんか?
・Cityクラス(高崎
・Prefectureクラス(群馬
・Regionクラス(関東
では書いてみよう。
・City
class City {
public:
void setPopulation(int p);
int getPopulation();
private:
int population;
};
void City::setPopulation(int p)
{
this->population = p;
}
int City::getPopulation()
{
return this->population;
}
・Prefecture
class Prefecture {
public:
~Prefecture();
void add(City* city);
int getPopulation();
private:
vector<City*> cities;
};
Prefecture::~Prefecture()
{
for (int i = 0; i < cities.size(); i++) {
delete cities[i];
}
}
void Prefecture::add(City* city) {
this->cities.push_back(city);
}
int Prefecture::getPopulation()
{
int result = 0;
for (int i = 0; i < cities.size(); i++) {
result += cities[i]->getPopulation();
}
return result;
}
・Region
class Region {
public:
~Region();
void add(Prefecture* prefecture);
int getPopulation();
private:
vector<Prefecture*> prefectures;
};
Region::~Region()
{
for (int i = 0; i < prefectures.size(); i++) {
delete prefectures[i];
}
}
void Region::add(Prefecture* prefecture)
{
prefectures.push_back(prefecture);
}
int Region::getPopulation()
{
int result = 0;
for (int i = 0; i < prefectures.size(); i++) {
result += prefectures[i]->getPopulation();
}
return result;
}
Prefecture、Region共に似ていますよね。これをまとめていきましょう。
パターン適用
まずはすべてのクラスに共通するgetPopulationメソッドをDistrictに抽出します。
class District {
public:
virtual int getPopulation() = 0;
};
次にCityに相当するUnitDistrictクラスを作成します。
class UnitDistrict : public District {
public:
virtual int getPopulation();
void setPopulation(int population);
private:
int population;
};
int UnitDistrict::getPopulation() {
return population;
}
void UnitDistrict::setPopulation(int population) {
this->population = population;
}
次にPrefecture、Regionを一つにまとめます。これをGroupDistrictとします。
class GroupDistrict : public District {
public:
~GroupDistrict();
void add(District* district);
virtual int getPopulation();
private:
vector<District*> districts;
};
GroupDistrict::~GroupDistrict()
{
for (int i = 0; i < districts.size(); i++) {
delete districts[i];
}
}
void GroupDistrict::add(District* district)
{
districts.push_back(district);
}
int GroupDistrict::getPopulation()
{
int result = 0;
for (int i = 0; i < (int)districts.size(); i++) {
result += districts[i]->getPopulation();
}
return 0;
}
k
コンポジットパターンを適用することで、コードの重複がなくなりました。
まとめ
・集団を構成するクラスと要素を構成するクラスを一様に扱える
・ツリー構造全体を同じ方法で扱える。
・新しいグルーピング単位を容易に追加可能
・新しいコンポーネントを簡単に追加できる
コメントを残す