Stateパターンと相性が悪い?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
チルチル

Stateパターンと相性が悪い?

#1

投稿記事 by チルチル » 15年前

前回

http://www.play21.jp/board/formz.cgi?ac ... 78&vino=81

の続きですが

構造を検討した結果
選択画面からゲーム画面へ飛ぶようなStateパターンの管理体制としては

世界クラスが場面クラスを包含して
場面クラスが使用するインスタンス郡を包含するという構造に決まったんですが

実装しようとすると相性が悪い気がするんですよね・・

まず次に飛ぶインスタンスを指定するのは今のインスタンスになりますが
包含である以上は他のインスタンスが見えないんですよね・・

場面クラスのヘッダをインクルードすれば見えない事も無いですが
指定する時に場面クラスのインスタンス名も書かなくてはいけないので見栄えが悪い上に
カプセル化でインスタンス郡は非公開ですからそもそも見えません

また列挙型を使うとStateパターンの意味が無い上に配列にしないといけない感じになって微妙です・・

画像の読み込みがあるので動的なインスタンスはダメだし効率は捨てなくてはいけない気がするんですよね・・

考えた結果唯一実現可能な方法として
インスタンス郡の数だけ世界と場面にポインタを返す関数を用意しておいて
インスタンス郡のコンストラクタで呼び出してメンバ配列に記憶して渡して使う方法です

何か列挙型を使うのと同じような気もしますが
一応これで行こうと思っています

しかしこのままだと後味が悪いので
何かもっと良い方法があったら教えてください

私としては最良の方法だと思うのですが
大事な部分だし前回のトビで最良が覆された前例があるので先人の知恵も借りようと思ったので・・

ねこ

Re:Stateパターンと相性が悪い?

#2

投稿記事 by ねこ » 15年前

その最良の知恵をくれた先人達は散々「まず作れ」って言ってたと思うんだけどまだ振り回すのかw

<場面クラスのヘッダをインクルードすれば見えない事も無いですが
<指定する時に場面クラスのインスタンス名も書かなくてはいけないので見栄えが悪い上に
これも指摘したけど「見栄えが悪い」とか「無駄に感じる」を質問の引き合いに出さないで下さい。
案を出しても「見栄えが悪い」の一言でスルーされる回答者の気持ちになってみたら?
最低でもこんなのはコーディングルールでも提示してから許されるもんです。

そもそも最良ってのは全体的な形があって初めて決まるものなのに
具体的な最終完成形も分からない(提示しない)のにそれを求めるってのは随分勝手じゃないですか?
前回の長々とした議論はなんだったの?提示された沢山のソースをちゃんと試したの?
参考にとお勧めされたURLのページはきちんと目を通したの?
知恵を借りる前に上記のように一杯「まだ試せる事」あるんじゃないの?

組木紙織

Re:Stateパターンと相性が悪い?

#3

投稿記事 by 組木紙織 » 15年前

あら、ねこさんちょっと怒りぎみかな。

どのような形でも一通り実装したのを見せてください。
効率化(演算速度のことですよね)はある程度完成が見えきてからするものです。
コードの見栄えの良さは経験によって変わるものです。

プログラミング言語は一応"言葉"なので、知識よりも経験がものを言います。
失敗したって誰からも怒られないと思うので、存分に失敗してください。
失敗してからなら、良い方法の良いところがわかります。

チルチル

Re:Stateパターンと相性が悪い?

#4

投稿記事 by チルチル » 15年前

>その最良の知恵をくれた先人達は散々「まず作れ」って言ってたと思うんだけどまだ振り回すのかw

いえいえ滅相も無い
ダメ押しもかねた軽い気持ちでの質問ですので
振り回すつもりなどはまったくありません

>これも指摘したけど「見栄えが悪い」とか「無駄に感じる」を質問の引き合いに出さないで下さい。

見栄えが悪いのは重大な欠陥だと思うのは私だけなんでしょうか・・

>案を出しても「見栄えが悪い」の一言でスルーされる回答者の気持ちになってみたら?

まあ確かに「見栄えが悪い」って言われたら困るとは思いますが、そうとしか言えないんですよね・・

>最低でもこんなのはコーディングルールでも提示してから許されるもんです。

何がコーディングルールかと言えば「自分から見て見栄えが良いコード」でしょうかね・・
「見栄えが良い」と言うのは状況によって変わるので実質無いですね、直感と言う事にしています

>そもそも最良ってのは全体的な形があって初めて決まるものなのに
>具体的な最終完成形も分からない(提示しない)のにそれを求めるってのは随分勝手じゃないですか?

無理があるとは思いましたが、質問しないよりはマシかと思ったもので・・

>前回の長々とした議論はなんだったの?提示された沢山のソースをちゃんと試したの?

私としては前回の議論はとても役に立ちましたよ
「まず作れ」と言うのは納得が行きませんが・・
ソースは6割方ぐらいは試しました

>参考にとお勧めされたURLのページはきちんと目を通したの?

一応すべて目を通しました・・

>知恵を借りる前に上記のように一杯「まだ試せる事」あるんじゃないの?

あるかもしれませんが私が思い付かないので無い事になります・・

>どのような形でも一通り実装したのを見せてください。
>効率化(演算速度のことですよね)はある程度完成が見えきてからするものです。
>コードの見栄えの良さは経験によって変わるものです。

残念ながらStateパターンが核なので、これを解決しないと実装できません・・

>プログラミング言語は一応"言葉"なので、知識よりも経験がものを言います。
>失敗したって誰からも怒られないと思うので、存分に失敗してください。
>失敗してからなら、良い方法の良いところがわかります

なるほど、先人の知恵ですね
まあ失敗したら私が自分に怒りますが・・

質問した時は最良を覆せないと思っていましたが
簡単に覆されてしまいましたね・・

つまり真の最良は「質問するより作った方がうまく行くと先人が教えてくれている」って事ですね

まだ半信半疑ですが、先人が口を揃えて言っているんだから疑いの余地は無いですね

では現状の方法で製作を開始してみようと思います
先人の皆様どうもありがとうございました

組木紙織

Re:Stateパターンと相性が悪い?

#5

投稿記事 by 組木紙織 » 15年前

別にゲーム画面が選択画面を直接呼ぶ必要はなくて、ゲーム画面は世界に選択画面に行ってくださいって
頼めばよいのです。
そうすれば世界はゲーム画面から選択画面に切り替えるという作業をすれば、
ゲーム画面が選択画面を知らなくてもうごきますよね。

/*********************
[追記]
>つまり真の最良は「質問するより作った方がうまく行くと先人が教えてくれている」って事ですね
いえ、そうではなく、
少なくとも私が言いたかったことは、
作ってみて(or作ろうとして)問題点を正しく把握した後に、問題となる部分を質問してくれたら、
無駄に言葉を重ねずに良い方法を知ることができ、そのよい方法の良い点がわかるということです。

*************/
#include <iostream>

enum MOVE{BACK,NEXT,NOW};
class Stage
{
private:
public:
virtual MOVE doing() =0;
};

class StartStage:public Stage
{
	MOVE doing();
};

class GameStage :public Stage
{
	MOVE doing();
};
class EndStage: public Stage
{
	MOVE doing();
};
MOVE StartStage::doing()
{
	std::cout << "This is start Stage: " << std::endl;
	int c;
	std::cout << "Please input number 1[NEXT] or 2[BACK] or another[NOW]" << std::endl;
	std::cin >> c;
	return (c==1)?NEXT:(c==2)?BACK:NOW;
}

MOVE GameStage::doing()
{
	std::cout << "This is game Stage" << std::endl;
	int c;
	std::cout << "Please input number 1[NEXT] or 2[BACK] or another[NOW]" << std::endl;
	std::cin >> c;
	return (c==1)?NEXT:(c==2)?BACK:NOW;
}

MOVE EndStage::doing()
{
	std::cout <<"This is end Stage" << std::endl;
	int c;
	std::cout << "Please input number 1[NEXT] or 2[BACK] or another[NOW]" << std::endl;
	std::cin>> c;
	return (c==1)?NEXT:(c==2)?BACK:NOW;
}

class World
{
private:
	Stage*		stage;
	Stage*		arr[3];
public:
	World();
	~World();
	void doing();
};
World::World()
{
	arr[0] = new StartStage;
	arr[1] = new GameStage;
	arr[2] = new EndStage;
}

World::~World()
{
	for(int i=0;i<3;i++)
	{
		delete arr;
	}

}
void World::doing()
{
	int index =0;
	while(index>=0 && index<=2)
	{
		MOVE mo;
		mo = arr[index]->doing();
		switch(mo)
		{
		case BACK:
			index--;
			break;
		case NEXT:
			index++;
		};
	
	}
}



int main()
{
	World w;
	std::cout << "gameStart" << std::endl;
	w.doing();
	std::cout << "gameEnd" << std::endl;
	return 0;
}

conio

Re:Stateパターンと相性が悪い?

#6

投稿記事 by conio » 15年前

チルチルさんは心配性のようですね。

ですが、ある程度方針を決めたら
頭の中で色々と考えるよりかは、実際にコードを書いていったほうが良いと思います。

あらゆることに適応できる万全なコードを、初期段階で頭の中で全て想定しておくのは
ほぼ無理です。
(必ず、想定外の問題が出てきたり、また途中で仕様を変更しようと判断し、修正の必要が出てきたりなどがあるかと。)


>>>参考にとお勧めされたURLのページはきちんと目を通したの?
>>一応すべて目を通しました・・
目を通すだけでは駄目かなと思います。

以前、クラス内遷移やらでURLを紹介される事もありましたが、
「よく分かりませんでしたね。」で一蹴されることもありました。

完璧とまでは行かずとも、理解しようとしたり、
また理解したのならば頭の隅にでも軽く留めておくことが必要だと思います。
(以前の質問の回答を忘れて、また同じ質問を繰り返したりすると、えらく非効率です)

Mikan

Re:Stateパターンと相性が悪い?

#7

投稿記事 by Mikan » 15年前

どうやら世界クラスという概念が先に来るので、難しくなってるように思います。

世界クラスの概念を捨てて

・プレイヤークラス
・敵クラス
・場面クラス

という独立した3つのクラスを作り、main()で正常に動作するまでカプセル化を行います。
※上記3つのクラスはお互いが見えないものとする

最後にmain()でやってたことを世界クラスにさせれば良いのではないかと思います。

Mikan

Re:Stateパターンと相性が悪い?

#8

投稿記事 by Mikan » 15年前

肝心なStateパターンのことを書くのわすれてました^^;

>>実装しようとすると相性が悪い気がするんですよね・・
無理に使わなくてもいいのでは?
デザインパターンは考え方なので、必ずしもそのプログラムに使える(最適)とは限りません。
使えるところは変更!って感じでもいいかと思います。

どうしてもStateパターンを使うのであれば、やはり場面クラスに実装してmain()から
使えるようにするのがいいですよ♪

MNS

Re:Stateパターンと相性が悪い?

#9

投稿記事 by MNS » 15年前

>世界クラスが場面クラスを包含して
>場面クラスが使用するインスタンス郡を包含するという構造に決まったんですが
このような設計よりも、世界クラスを包含する新たなクラスを作り、
そのクラスが場面クラスを使用する、という構造をとったほうが良いと思います。
class Game

class State
{
	virtual void Update(Game* pgame) = 0;
};

class Game
{
	World* world;
	State* state;

public:
	void Update(){ state->Update(this); }
	void ChangeState(State* newstate)
	{
		delete state;
		state = newstate;
	}
	World* getWorld(){ return world; }
	Game()
	{
		state = new BeginningState();
		world = new World();
	}
};

class BeginningState :public State
{
	void Update(Game* pgame);
}

class MainState :public State
{
	void Update(Game* pgame);
}

void BeginningState::Update(Game* pgame)
{
	//Worldのメンバへアクセスしたい場合は、
	pgame->getWorld()->/* member */
	//別のステートに遷移したい場合は
	if(/* 条件 */)
		pgame->ChangeState(new MainState());
}
などなど・・(コードはコンパイルをしてないのでもしかしたら誤ってるかもしれません)
場面を動的確保したくなければ、場面ごとシングルトンにして、そのポインタを渡すようにしてください。

いろいろとあると思いますが、気を落とさず挑戦してみてください

チルチル

Re:Stateパターンと相性が悪い?

#10

投稿記事 by チルチル » 15年前

なるほど列挙型指定ですね
これでも良いんですがヘッダのインクルード箇所が増えて管理しきれない気がするんですよね

>別にゲーム画面が選択画面を直接呼ぶ必要はなくて、ゲーム画面は世界に選択画面に行ってくださいって
>頼めばよいのです。

いえ、そうではなくて場面の中で次に進む場面を指定する時に
次の場面が見えない構造だから工夫が必要という事です

>目を通すだけでは駄目かなと思います。

正確には目を通して、ある程度は理解しました・・

>以前、クラス内遷移やらでURLを紹介される事もありましたが、
>「よく分かりませんでしたね。」で一蹴されることもありました。

わからないコードは自分が使えないので
正直に「わかりませんでした」と言った方が誤解を生まないと思ったのですが・・

>無理に使わなくてもいいのでは?

確かに実装しようとすると方法は重要では無かったですね・・

>このような設計よりも、世界クラスを包含する新たなクラスを作り、
>そのクラスが場面クラスを使用する、という構造をとったほうが良いと思います。

そういう手もあるんですが包含の階層が多くなると
私が理解できなくなって管理できなくなりそうで怖いです・・

さらに入力やループ関係との繋がりが曖昧になる上に
階層が増える事でアクセサの数が増大してコードの可読性が下がる問題もあります

カプセル化を守るためにはメンバに直接アクセスしてはいけないので
アロー演算子を使った2段階アクセスはNGです・・

>などなど・・(コードはコンパイルをしてないのでもしかしたら誤ってるかもしれません)
>場面を動的確保したくなければ、場面ごとシングルトンにして、そのポインタを渡すようにしてください。

なるほどインスタンスして渡すんですね

方法としては色々とあるんですが実装する段階になると
状態変化の方法よりも次の状態が見えない事が問題になって来たんですよね・・

包含はすべてインスタンスで持つというルールを決めたのでそこは変えない方向の予定ですが
さらに考えるといちいちアクセサを作るのは面倒なので引数に文字列を渡して内部で分岐する方法を考えました

分岐を無くす為の準備で分岐をするというのも変ですが細かい事を気にしていると前に進まないですね・・
アクセサがインライン化されにくそうで実行ファイルが大きくなりそうですが
まあコンストラクタで呼ぶと思うのでオーバーヘッドは関係ないですし・・

良い忘れましたが選択画面の汎用化のためにポインタを最初から配列で持っておく必要があるんですよね
それを実現するにはこれしかないかなと・・

今になって思うと素直にスイッチ文を使えば一発で解決したんですけどね・・
まあ素材の管理が大変なので無理なんですが・・

しかし教えてもらったサイトは役に立ちましたよ
sprite.SetTexture((CTexture*)FindItemBox("zakotex"));
と言う記述を見て思い付きましたから

World.SceneGet("Title");//タイトル画面のポインタを返す

このような関数を作ると1つで全部のポインタを調べられて便利と言う事ですね、勉強になりました
インスタンスごとに別々にアクセサを作るのとどっちが良いかはわかりませんが
とりあえず私が楽なのでこの方法でやってみましょうかね・・

チルチル

Re:Stateパターンと相性が悪い?

#11

投稿記事 by チルチル » 15年前

そういえば前回のトビで気になってる事があるんですが

「メンバごとにアクセサを作るのは無駄」と言うアドバイスと

「メンバごとにアクセサを作った方が良い」と言うアドバイスがあったのですが

結局どっちなのでしょうか?

案外、両方を満たしている?のは

World.SceneGet("Title");

こういう事なんでしょうかね・・

MNS

Re:Stateパターンと相性が悪い?

#12

投稿記事 by MNS » 15年前

前回のトピックスで二つの意見があったということは、
二つの異なる見解が存在するということで、結論付けることは出来ないと思います。

私の意見では、外部からアクセスを受けるメンバに対しては、
カプセル化の原則に基づいて、全てアクセサを作る必要があると考えます。
アクセサを作らないのは、あくまで速度を重視する場合であるか、
そこまで厳格なカプセル化が必要ないメンバに限るでしょう。

チルチル

Re:Stateパターンと相性が悪い?

#13

投稿記事 by チルチル » 15年前

アクセサを作りたくないのは数が多くなるとゴチャゴチャする事でしょうかね・・

それから包含がある以上は自機がボスの座標を知りたい場合に

自機が世界のアクセサを呼び出して
世界のアクセサがキャラのアクセサを呼び出して
キャラのアクセサがボスのアクセサを呼び出して
ボスのアクセサがボスの座標を返す

と言う事になってしまい

メンバ1個につきアクセサを3個作らなくてはいけないと言う状況になるんですよね・・

メンバを調べるだけでアクセサの連鎖が凄い事になるのは怖いですが
作ってしまえば管理はしやすいかもしれませんね・・

MNS

Re:Stateパターンと相性が悪い?

#14

投稿記事 by MNS » 15年前

アクセサだけまとめて集めれば、それほど可読性が損なわれるわけではないですし、
カプセル化が破綻するよりはマシだと個人的には思います。
>メンバ1個につきアクセサを3個
長い目でみれば、他で"世界のアクセサ"や"キャラのアクセサ"を使うことも考えられますし、
無駄な作業でもないでしょう。

ところで、Stateの件ですが、構造がいまいち掴めません。
とりあえずやってみるとのことなので、まだスッキリしないという場合には、
一通り構造を組んだあと、コードを提示してくだされば適当な回答が得られると思います。

チルチル

Re:Stateパターンと相性が悪い?

#15

投稿記事 by チルチル » 15年前

包含しているクラス内のアクセサは見えないので集めるのは無理ですが
ヘッダのインクルードを減らすために
自機→世界→キャラ→自機とスコープがループするような構造にする予定なので
「世界のアクセサ」や「キャラのアクセサ」を使うとしたら「世界」や「キャラ」になりますね
それも便利そうなので無駄ではなさそうです
この辺は慣れの問題のようですね、実際にやっていればそれほど気にならなくなると思います

Stateがスッキリしない理由はアクセサが多くなって管理しづらいと言うのが大きいので
そこを割り切ればそれほど問題では無いかもしれません

と言うより動的なインスタンスはしないと言う前提があるので
場面のインスタンス郡は場面管理クラスが包含するしかありません
次の場面に進むには次のインスタンスのポインタとか番号が必要ですが
カプセル化されているので場面からは次の場面が見えません
となるとアクセサを作るしかないので、もう結論は出てるのかもしれませんね・・

でもアクセサだけ集めるのも兼ねて

やはり

World.SceneGet("Title");

これぐらいの汎用化はしても良いかもしれませんね

これは別にカプセル化を壊してないし
内部で分岐しているだけなのでやってる事は同じになりますが

メモリに文字列が大量に展開されるのは怖いですね・・

MNS

Re:Stateパターンと相性が悪い?

#16

投稿記事 by MNS » 15年前

No.40735でも言いましたが、ステート+シングルトンではダメなのでしょうか?
具体的なコードでいうと・・
class Game

class State
{
public:
	virtual void Enter() = 0;
	virtual void Exit() = 0;
	virtual void Update(Game* pgame) = 0;
};

class Game
{
	World* world;
	State* state;

public:
	void Update(){ state->Update(this); }
	void ChangeState(State* newstate)
	{
		state->Exit();
		state = newstate;
		state->Enter();
	}
	World* getWorld(){ return world; }
	Game();
};

class BeginningState :public State
{
	BeginningState(){}
public:
	void Enter(){/*コンストラクタ的な役割*/}
	void Exit(){/*デストラクタ的な役割*/}
	void Update(Game* pgame);
	static BeginningState* Instance()
	{
		static BeginningState bs;
		return &bs;
	}
}

class MainState :public State
{
	MainState(){}
public:
	void Enter(){/*コンストラクタ的な役割*/}
	void Exit(){/*デストラクタ的な役割*/}
	void Update(Game* pgame);
	static MainState* Instance()
	{
		static MainState ms;
		return &ms;
	}
}

void BeginningState::Update(Game* pgame)
{
	if(/* 条件 */)
		pgame->ChangeState(MainState::Instance());
}

void MainState::Update(Game* pgame)
{
	//Worldクラスの更新
	pgame->getWorld()->Update();
}
なぜ、動的確保してはいけないのか疑問ですが、
シングルトンと組み合わせるならばこんな感じです。
>カプセル化を守るためにはメンバに直接アクセスしてはいけないので
>アロー演算子を使った2段階アクセスはNGです・・
これもよくわかりません。もちろん、privateのメンバへはアクセスできませんよ。

チルチル

Re:Stateパターンと相性が悪い?

#17

投稿記事 by チルチル » 15年前

ああ確かに場面のクラスを全部同じヘッダにまとめればシングルトンが見えますね
動的確保せずインスタンスを実体で持つ理由は世界に全部のクラスを合体させるためですが
これは中々使えるかもしれませんね

場面クラスから別の場面クラスが見える時点でカプセル化が崩壊していますが、まあ今は置いておくとして・・

しかしシングルトン用の静的メンバ関数をいちいち作るのは非常に大変ですね・・
ものがインスタンスだけに基底クラスで済ます事もできないし・・

動的確保してはいけない理由としてコンストラクタで画像のロードを行うので
画像を静的メンバにしたり何回目のインスタンスか数えたりするのは手間が掛かりすぎると言うのが挙げられます

ですがシングルトンの場合はゲーム内でタイトル画面から全部の画面に移動できるので
初期状態としてタイトルをインスタンスすると全部のクラスにインスタンス化が広がっていく気もしますね
シングルトンでもコンストラクタで移動先のポインタを取得する事に変わりないですから・・

なかなか良いとは思いますがアクセサを使う場合よりコードの量が増えるし
枝先は根本だけに依存すると言う大前提を破壊するのは気が引けますね・・
ですが便利そうなのは確かなので迷いますね・・

dic

Re:Stateパターンと相性が悪い?

#18

投稿記事 by dic » 15年前

>インスタンス郡の数だけ世界と場面にポインタを返す関数を用意しておいて
>インスタンス郡のコンストラクタで呼び出してメンバ配列に記憶して渡して使う方法です
ファミコンなどアセンブラで数バイト単位で戦ってこられた方が聞いたらキレますね
私はポインタのハードコーディングスタイルは嫌いです
それならCでいいんじゃないかと

Stateパターン(C++)とC言語スタイルを比べるのはスジが違うのでは?

チルチル

Re:Stateパターンと相性が悪い?

#19

投稿記事 by チルチル » 15年前

う~ん仰っている意味が良くわからないんですが・・


>ファミコンなどアセンブラで数バイト単位で戦ってこられた方が聞いたらキレますね

すみません、ファミコンとアセンブラは見た事が無いのでピンと来ないです


>私はポインタのハードコーディングスタイルは嫌いです

まず「ハードコーディング」と言う言葉を知らなかったので調べたんですが

1.特定の動作環境を決め打ちして、その動作環境で動作させることを前提とした処理やデータをソースコードの中に書き込んでしまうプログラミング方式

2.最初に作った人にとっては何らかの意味を持っているのであろうけれど、後から見る人にとっては意味不明の数字などがプログラムのあちこちに直接書いてある事

3.プログラム中に定数などを直接記述すること

と言うような結果が得られましたが、今回はどの意味でしょうか?

1は動作によって変わるような物でもなさそうなので違いますね、外国語までカバーする余力は無いですし

2は関数なので全く違いますね

3も関数なので全然違いますね

「ポインタのハードコーディングスタイル」とはどういう意味なんでしょうか?


関係無いですが、調べている時に「コーディングスタイル」の意味が書いてありました

>そのプログラミング言語の文法上ではどっちを使っても同じ意味で、無頓着な第三者にとってはどうでも良いような事だが
>しかし「プログラムを作る事は芸術だ」と信じて疑わない当の本人にとっては他の何よりも重大事であると思い込んでいる
>神経質なプログラマの強迫神経症的な病的なこだわりの集合体の事

こういう意味の言葉だとは知りませんでしたね

代表的な例として書いてあったのが

・変数名は最初の一文字を必ず大文字にする。 単語の区切りなどはアンダーラインを使わず、大文字にする。
・意味を持った定数はハードコーディングせず、必ず全て大文字で構成されたマクロや何らかの変数を使用する。
・インデントはタブ1つで4文字文にする。
・ifやfor、while、switchなどのブロックの開始のカッコ(Cやその文法をパクった言語で多用される'{''のこと)は、次行に書かず、必ず同一行に記述する。
・式の評価の優先順位に影響を与えない不必要なカッコ(ここでは'('と')'のこと)は、必要最低限以上には絶対に使わない。

多少の違いはありましたが全部当てはまっているので1人で大爆笑したんですが
まあ前回のトビじゃないですけど、こんなのは考え方の問題なのでまったく関係ないですが・・


>それならCでいいんじゃないかと

Cはクラスが無いから無理です


>Stateパターン(C++)とC言語スタイルを比べるのはスジが違うのでは?

これも意味が良くわからないんですが、どういう事ですか?

そもそもカプセル化ってこういう事じゃないんでしょうか・・

構造の核ではありますがコンストラクタの初期化専用なのでそれほど全体に影響は無いですしね・・

Poco

Re:Stateパターンと相性が悪い?

#20

投稿記事 by Poco » 15年前

>そもそもカプセル化ってこういう事じゃないんでしょうか・・

MNSさんの投稿に対する返信を見る限り、カプセル化を勘違いしていませんか?
カプセル化ってのは、あるオブジェクトの状態(メンバ変数)を知るため、変更するためには
手続き(メンバ関数/ただの関数)を通す必要があるってことです。
あるクラスのメンバ関数の定義に別のクラスのオブジェクトがあるってだけでは、
カプセル化が崩れたということにはなりません。

話は変わりますが、私個人としては、見栄えは非常に重要と考えています。
他の回答者も間違いなく重要と考えているはずです。
ただ、チルチルさんから現物のコード、またはサンプルコードを提示して頂けていない為、
誰もチルチルさんの悩みを、理解・共有・共感できないのです。
見栄えの悪いと思っているStateパターンのサンプルコードを提示できないでしょうか?

チルチル

Re:Stateパターンと相性が悪い?

#21

投稿記事 by チルチル » 15年前

あ~そういえばそうでした・・
正しくは構造イメージが崩れるですね

何か知識を得るたびにコーディングスタイルが激化して行く気がするんですが
枝先が根本以外を呼び出すのはやりたくないですね・・
こっちの方が便利ではありますが手間もかなり増えますしね・・

見栄えはわがままに近いので共感までしていただこうとは思っていませんが
まだ見栄えの悪いStateパターンのコードは存在しません・・

皆さんの仰るとおり心配性なので
発生する事がわかっている問題は発生する前に回避しようとしてしまうんですよね・・
その結果まだ発生していない問題について質問する事になって回答者の皆さんに迷惑をかけてしまうんですが・・

どうもこの流れは良くないですね、多少納得が行かなくても実装してしまえば何とか動くと思いますから
あまり深く考えずに作った方が良いんでしょうかね・・

最低限はっきりさせたいのは
インスタンス郡の数だけアクセサを作るか
シングルトンを使うかですね

前者はアクセサを大量に作る必要があり
後者は静的関数を大量に作る必要がある

これは迷うので皆さんの意見を聞かせてください

Poco

Re:Stateパターンと相性が悪い?

#22

投稿記事 by Poco » 15年前

>正しくは構造イメージが崩れるですね

その構造イメージが間違っています。

Stateパターンでは、具体的な状態を表す全てのクラスは一蓮托生です。
具体的な状態を表すクラス(BeginningStateやMainState)に状態の追加や状態遷移の
変更が加わると、その影響は最大で具体的な状態を表すクラスは全てに渡ります。
逆に、その影響を根本クラス(Game、State)に「波及させないことを目的とした」
コーディング方法がStateパターンなのです。

つまり、BeginningStateクラスからMainStateクラスが見えたって
何の問題もないのです。

構造という点では、抽象層と具象層に分かれます。
抽象層(根本)に属するのがGame、Stateクラスで、
具象層(枝先)に属するのがBeginningStateやMainStateクラスとなります。

>何か知識を得るたびにコーディングスタイルが激化して行く気がするんですが

逆に言うと、中途半端な知識で理想を追求することは出来ない、って
うすうす認識されているのですよね?
私も同感、「下手な考え休むに似たり」です。
あまり深く考えずに作ったものを見てもらったほうが良いと思います。

Stateパターンに関して、MNSさんが提示してくださったサンプルが
お手本になると思います。

>最低限はっきりさせたいのは
>インスタンス郡の数だけアクセサを作るか
>シングルトンを使うかですね

アクセッサとシングルトンって何か関係あるのでしょうか?

dic

Re:Stateパターンと相性が悪い?

#23

投稿記事 by dic » 15年前

>Cはクラスが無いから無理です
switch文つかえばstateパターンなら実装できます

見栄えが悪いから考えてるんですよね?


>前者はアクセサを大量に作る必要があり
>後者は静的関数を大量に作る必要がある

>これは迷うので皆さんの意見を聞かせてください
何が言いたいの?意味がわからない

MNS

Re:Stateパターンと相性が悪い?

#24

投稿記事 by MNS » 15年前

どうも、チルチルさんはStateデザインパターンのメリットが良く分かっていないような印象を感じます。
Stateデザインパターンを使ったほうが、コードの量も減るでしょうし、見栄もよくなると思いますが。
結局のところ、文字で伝えるには限度がありますから、実際にコードを書かないと分からないと思います。
一度、Stateデザインパターンを使わない場合と、使う場合で簡単なゲーム画面を作ってみましょう。
百聞は一見にしかず、恐らくメリットが理解できるはずです。
もしも、プログラムが完成して、どうも納得いかない点があれば、そのコードを提示すれば、
私も含め、皆さんも適当な回答がしやすいと思いますよ。

チルチル

Re:Stateパターンと相性が悪い?

#25

投稿記事 by チルチル » 15年前

やっぱり頭の中だけで考えすぎなんでしょうね
これは「考えてるとキリが無い」と割り切った方が良さそうです・・

良く考えたらstateパターンを使った事が無いのに執着しても意味が無いですね・・
パターンがどうとかは忘れて「ポインタが指している場所を変更して状態が変わる」と言う構造だけ考えます

その構造で考えるとシングルトンの包含は開放タイミングが不明確なので不向きですね
やはりインスタンスを包含して1つのアクセサ内で分岐してポインタを返した方が良さそうです
加えてハードコーディング防止用にアクセサをマクロで呼び出して見ます
文字列の多数展開はともかく、そうすると構文が短くなるし修正がしやすそうですからね

ではそんな感じで作ってみたいと思います
うまく行かなかったら改めて質問させていただきます

今回も皆様のおかげで大変勉強になりました
どうもありがとうございます

閉鎖

“C言語何でも質問掲示板” へ戻る