【C++】コンポジットを実装したよ

コンポジットパターンは、

・要素の集合を表現するオブジェクト

・その集合に含まれる要素を表現するオブジェクト

を一様に扱えるようなデザインパターンです。

 

適用前

まず、皆さんがやるとしたら下記の様にクラスを用意しませんか?

・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

コンポジットパターンを適用することで、コードの重複がなくなりました。

まとめ

・集団を構成するクラスと要素を構成するクラスを一様に扱える

・ツリー構造全体を同じ方法で扱える。

・新しいグルーピング単位を容易に追加可能

・新しいコンポーネントを簡単に追加できる

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です