例えば図形クラスという親クラスがいて、その下に三角形、四角形、円形、楕円形、星型、等の具体的な子クラスがいるとします。今ファクトリーパターンで図形を生成しているのですが、それぞれの図形が持つ初期値をどう設定しようか迷っています。
例えば四角形はx, y, width, heightが必要ですが、円形ではcenterX, centerY, radiusが必要になります。今の私の設計では、それぞれのインタフェースを用意しているのですが、図形が増えるたびに、そのインタフェースが増え、ある図形専用の関数(下の例だとcreate)が増えてしまいます。
こういった場合にはどのように対処するのが良いのでしょうか?初期化のパラメタを抽象化すれば良いような気がしますが、具体的な解決策が思い浮かびません。
//!< main.cpp
enum ZUKEI {
SHIKAKU=0,
EN = 1.
SANKAKU = 2,
…
}
Zukei* sankaku = zukeiFactory.create(SHIKAKU, x, y, width, height);
Zukei* shikaku = zukeiFactory.create(EN, centerX, centerY, radius);
//!< ZukeiFactory.cpp
Zukei* ZukeiFactory::create(int zukeiId, int x, int y, int width, int height){
switch(zukeiId) {
case SHIKAKU:
return new ShikakuZukei(x, y, width, height);
case EN:
//???return new EnZukei();
}
}
Zukei* ZukeiFactory::create(int zukeiId, int centerX, int centerY, int radius) {
switch(zukeiId) {
case SHIKAKU:
//???return new ShikakuZukei();
case EN:
return new EnZukei(centerX, centerY, radius);
}
}
宜しくお願いします。
No.2ベストアンサー
- 回答日時:
> 図形が増えるたびに、そのインタフェースが増え
そのためのファクトリーパターンでは?
まずは #1 の方のとおり、使用するクラスを整理することですね。三角形・星型→多角形など。
それと、動作を enum ZUKEI のパラメータで変えている意味がわからないので、メソッド名を createRectangle, createCircle などにすべきでしょう。
他に例えば、長方形と楕円から大きさパラメータをくくりだして size(int width, int height) のように factory の状態を変化させればいいかもしれません。
例
class ShapeFactory {
int x, y, centerx, centery, width, height;
public:
Shape *createRectangle();
Shape *createEllipse();
Shape *createCircle(int radius);
...
void size(int width, int height);
void pos(int x, int y);
void center(int x, int y);
...
};
使用例
Shape *rect = factory.pos(10,10).size(100,50).createRectangle();
Shape *ellipse = factory.center(50,50).size(50,30).createEllipse();
Shape *circle = factory.center(50,50).createCircle(50);
No.1
- 回答日時:
> Zukei* sankaku = zukeiFactory.create(SHIKAKU, x, y, width, height);
> Zukei* shikaku = zukeiFactory.create(EN, centerX, centerY, radius);
変数名と作っている図形が異なっている件
……はおいといて、こんな感じかなぁ。
enum ParameterType {
POSITION,
RECT_SIZE,
RADIUS,
POSITIONS,
// ...
}
class Parameter {
public:
Parameter(ParameterType type) : type_(type) {};
virtual ~Parameter() = 0;
ParameterType getType() const {return type_;};
private:
ParameterType type_;
};
class Position : public Parameter {
public:
Position(int x, int y) : Parameter(POSITION), x_(x), y_(y) {};
~Position() {};
int getX() const {return x_;};
int getY() const {return y_;};
private:
int x_;
int y_;
};
// 以下、上記と同様に矩形サイズ、半径、点列(三角形とか星型で使うはず)クラスを作成
// 点列は個数を固定するより std::vector<Position> を使ったほうがいいかも
struct ParameterSercher {
ParameterSercher()
ParameterSercher(ParameterType type) : type_(type) {};
bool operator()(const Parameter* param)
{
return param->getType() == type_;
}
private:
ParameterType type_;
}
Zukei* ZukeiFactory::create(int zukeiId, const vector<Parameter*>& params)
{
switch(zukeiId) {
case SHIKAKU:
vector<Parameter>::const_iterator i_pos = find_if(params.begin(), params.end(), ParameterSercher(POSITION));
vector<Parameter>::const_iterator i_rect_size = find_if(params.begin(), params.end(), ParameterSercher(RECT_SIZE));
if (i_pos == params.end()) || (i_rect_size == params.end()) return NULL;
int x = dynamic_cast<Position*>(*i_pos)->getX();
int y = dynamic_cast<Position*>(*i_pos)->getY();
int width = dynamic_cast<RectSize*>(*i_rect_size)->getWidth();
int height = dynamic_cast<RectSize*>(*i_rect_size)->getHeight();
return new ShikakuZukei(x, y, width, height);
case EN:
// 以下、上記と同様
}
}
Position* sankaku_pos = new Position(x, y);
RectSize* sankaku_rect = new RectSize(width, height);
vaector<Parameter*> params;
params.push_back(sankaku_pos);
params.push_back(sankaku_rect);
Zukei* sankaku = zukeiFactory.create(SHIKAKU, params);
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- PowerPoint(パワーポイント) ExcelのVBAコードについて教えてください。 3 2022/05/25 14:32
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- MySQL my_itemsテーブルのIDにAUTO_INCREMENT を追加ができるかで 1 2023/01/03 09:09
- C言語・C++・C# #include <stdio.h>int main(void) { int buf[100] = 6 2022/11/01 22:45
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
if と配列の組み合わせ
-
複数桁10進数の*桁目だけを抽出...
-
「指定されたキャストは有効で...
-
(int *)の意味
-
足して100になるような乱数のア...
-
PowerShellがうまくいかない
-
C言語 エラーの原因がわからな...
-
C言語で行列の積を計算できるよ...
-
C#で配列の分割
-
ポインタを使って関数の値の...
-
C言語 逆順の配列の仕方を教え...
-
因数分解を行うプログラムについて
-
各桁の和を返す関数
-
引数 戻り値 return文について
-
C言語で三目並べをするプログラ...
-
円周率
-
C言語の問題です。大至急回答お...
-
わかりません・・・。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
複数桁10進数の*桁目だけを抽出...
-
#define _CRT_SECURE_NO_WARNIN...
-
ラップ関数とはどんなものですか?
-
卒業研究でよく分からないとこ...
-
【C++】関数ポインタの使い方
-
実数の整数部,小数部の取得
-
std::set<int> で、ある値が何...
-
C言語 エラーの原因がわからな...
-
c言語
-
system関数がうまくいかない
-
C++でvectorにテキストファイル...
-
acceptをalarmでタイムアウトさ...
-
if と配列の組み合わせ
-
return 1L
-
「{ } で囲むだけ」は正しい?
-
(マルチスレッド)_beginthrea...
-
PowerShellがうまくいかない
-
このプログラミング誰か教えて...
おすすめ情報