質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

2回答

3089閲覧

ロジック処理と出力処理の分け方

mightyMask

総合スコア143

MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

4グッド

3クリップ

投稿2017/02/24 23:28

編集2017/02/25 11:55

#前提
javaのswingを用いてGUIの将棋ソフトを作成しています。
ほぼ趣味プログラマーであり、プログラミング初心者です。
厳格で純粋なオブジェクト指向に近いコードで綺麗に書く事を目標とします。
そのため、早く軽快な動作は期待しません。
ソースコードを短くするという事も期待しません。

#制作途中のクラスの関係
MVC(Model View Controller)の考え方に添い、3つのパッケージに分割しています。
Controller
入力制御クラス(入力から盤面クラスに指示)
View
画面出力クラス
Model
駒クラス(抽象)
歩、金、成桂などのクラス
升クラス(1つの駒クラスと、先手後手どちらの駒であるかを保持)
盤面クラス(81つの升クラスを保持)

#質問
画面出力クラスが盤面クラスの情報を知り、その情報から表示する駒の画像を決める。
この処理をどうすれば良いのかどうしても思いつきません。
何かアイディアをください。

ただ実装すれば良いだけなら2通りの方法が思い浮かびましたが、どちらも良い方法ではありません。
1.盤面クラスのメソッド(引数は座標)を呼んで升クラスを返して貰えば、画面に表示させるのに必要な情報がわかる。
その情報からifかswitchを使い画像を選択する。
これは全くオブジェクト指向的ではないので問題外です。
2.駒クラスが最初に画像を読み込み保持しておく。そして盤面クラスのメソッド(引数は座標)を呼び、駒の画像を返してもらう。
この場合MVCの役割が破綻しています。

#追記
目的に対して適切な手段を取るのが正解との事で、ModelとViewに分ける目的をある程度はっきりとさせておきます。
後にコンソールで動く将棋ソフトを作る際、Model部分を変更させずに再利用できる様にすると言う事が目的です。

stereo_code, Chironian, miiichat, maisumakun👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Chironianさんが回答されていることにかぶっている気もしますが・・

問題はその中身が駒の種類毎にifかswitchによる分岐が発生するので、当初の問題を解決できていないことです。

if/switchを無くしたいあるいは「金が銀の状態に変化することがないのに駒の種類をstateパターン的に捉えるのはいやだ」ということであれば、駒の種類に応じたクラスを作るという方向になると思います。

java

1classView { 2 private Image image; 3 4 protectedView(Image image) { 5 this.image = image; 6 } 7 8 @Override public void paintComponent(Graphics g) { 9 g.drawImage(image, 0, 0, getWidth(), getHeight(), this); 10 } 11} 12 13classView extendsView { 14View() { 15 super(loadImage("王.png")); 16 } 17} 18 19classView extendsView { 20View() { 21 super(loadImage("玉.png")); // 王と玉は違うから...w; 22 } 23} 24...

さて、先手と後手で画像が180度回転させたものになる点はどうでしょうか。厳密に言えば「先手駒」「後手駒」を作ることもできますし「先手」「後手」をstateとして捉えることもできます。ここからは作りの問題にもからみますが盤面にある状態では先手・後手が変化することはありえないのでstateじゃいやだという考え方なら先手駒・後手駒のクラス分けにしてもいいのかも知れません。しかし駒が取られるとその駒の先手・後手が逆転するのだからこれはstateと考えることもできます。

前者だと駒が取られたら盤面から消えるとともに駒Viewインスタンスも消えて新たに先手後手が逆転したインスタンスを生成してそれを「駒台View」に追加なんて実装になります。一方後者なら取った駒は先手・後手のstateを変更しそのインスタンスそのものを「駒台View」に追加になるでしょう。(盤面Viewとは別に駒台Viewがあると仮定してます)if文やstateを排除して作りたいことにこだわるなら前者でしょうし、現実の動きに即したインスタンスのライフサイクルに即して作りたいと思ったら後者になるでしょう。

さらに成った時に画像が変わりますがこれはstateパターンで実装するのが自然な感覚がしますが、やはりif/switch/stateじゃいやクラス分けをして成る前の駒は消失し新たに成った状態の駒を生成してそれを盤面Viewへ配置とすることもできます。

Chironianさんもおっしゃっているように「絶対にこうしなければならない」というより「より適切な方法を適宜とる」というのがプログラミングでの心構えだと思います。より厳密にというのが「現実世界での振る舞いと極力合わせて」ということなのか「プログラム上からif/swichを排除する」ことかによって取るべき方法は変わると思いますが、自分で納得できるまで厳密に考えてみるのも面白いと思います。個人的にはif/switchを排除することより現実世界の振る舞いに似たものにすることの方が有用と感じることが多いです。また「クラスを分けて作ることはできるけど手軽だから配列とコードで違いを表現」という手もはやりよく使います。厳密なクラス分けの価値と配列ルックアップの手軽さを天秤にかけるわけですw;

投稿2017/02/25 03:39

編集2017/02/25 03:42
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chironian

2017/02/25 04:21

横から失礼します。 "王View"や"玉View"のインスタンスをView側でnewする必要がありますが、View側は静的には駒の種類を保持していないため、ifやswitchで動的に判別してnewするしかないです。(一見できそうでできないんですよ。) と思ってましたが、すいません、これはC++思考でした。 リフレクションを使えば動的にモデル側の型名をとれますし、それを加工してビュー側のクラス名へ変換して、そのインスタンスをたぶん作れますね。(Javaではやったことないですが、C#ではできました。) リフレクションは折角の型チェックをスルーするので、使わないで済む時は使わない方がよいですが。
KSwordOfHaste

2017/02/25 09:25

おっしゃるとおりだと思います。個々のインスタンスの振る舞い自体はis-aによる関係でif/switchの排除が可能ですが、あるModelクラスとあるViewクラスの対応関係については結局のところ「王Modelなら王Viewを使う」ということをどこかに定義しなければならずそれはif/switchを書かないようにするためになんらかの連想テクニックを使ったとしてもよく考えてみるとその本質は「if」であることにはかわりないように思えます。唯一メタ情報をhas-aとしておき、 駒View createView(駒Model km) {  return km.getViewFactory().newInstance(); } とするとif/swtich的なものを排除できる気もしますがこうやると「ModelがViewのファクトリーを返さなきゃいけなくなるなぁ・・・」という点があまり気持ちよくない気がします。メタ情報なんだから「よいではないか」という心の声も聞こえますが。 やはりこのあたりは「このこだわりって何か意味あるのかな」となってしまいどこかで妥協することになる気がします。もっと厳密にif/switch的なものを排除する方法論があるのでしょうか・・・自分には思いつけませんw;
Chironian

2017/02/25 11:00

目的に対して適切な手段を使うのが正解と思います。 もし、MVCが有効となるケース(スキンを切り替えたい、デザイナーが独立して作業できるようにしたいなど)では、モデルがビューに依存するとかなり辛いので、メタ情報といえど依存するべきでないでしょう。 しかし、この質問のケースもそうですが、モデルをビューから独立させる際にそれなりのデメリットを伴うケースも少なくありません。そのような時で、しかもMVCを採用するメリットがそれ程大きくないプロジェクトなら、MVCに拘るのは本末転倒と思います。 要は手段に拘って目的を見失わないことが大事と思います。 > もっと厳密にif/switch的なものを排除する方法論があるのでしょうか if/switchに較べて表は自由度は低いですが、その分プログラムのバグが入り込む余地が少ないです。 なので、今回のようなケースで、かつ、MVCが有効な時は私なら表を使うと思います。 でも、そもそもMVCが無駄な場合も少なくないので、そのような時は躊躇なくモデルをビューに依存させ、メンテナンスしやすいようにすると思います。
guest

0

ベストアンサー

こんにちは。

面白い問題ですね。Stateパターンを使って駒の描画を切り替えたいけど、それではモデル側に描画処理が入ってしまいMVCから逸脱するので、何か良い案はないか?ってことですね。
スキンを切り替えた時、駒のデザインも切り替えたいような場合に実際に発生しそうな問題です。

駒のデザイン切り替えをサポートする場合、モデルがビューに依存しない構造はたいへん好ましい設計と思います。となると、2.はモデルがビューに依存するため、1.をベースに考えざる得ないと思います。
なので、そこにstateパターンを適用できないか考えるべきでしょう。

例えば、モデル側の駒クラス経由で駒オブジェクトを受け取り、駒画像を返却するような機能を持つビュー側駒クラスを考えることは可能ですね。
そして、そのビュー側駒クラスはデザイン毎に派生クラスを作りStateパターンを適用すると、デザインの拡張に対応しやすいです。
問題はその中身が駒の種類毎にifかswitchによる分岐が発生するので、当初の問題を解決できていないことです。

デザインは通常 駒にインデックス番号などを振って駒画像をテーブルで管理すると思います。駒画像のメンテナンスもそうしておかないと辛いですし。
であれば、駒オブジェクトからインデックス番号などを受け取って、そのテーブルを引いて画像を返却する構造にすれば、駒の種類が増えてもテーブルの要素を増やすだけで済み、分岐コードの改造は不要ですのでStateパターンのメリットと同様なメリットを享受できます。表の追加の方がクラス追加より手間は少ないです。そして、これはデザイン切り替えしない時にも適用できます。

しかし、このアイデアはオブジェクト指向プログラミングかというと、微妙です。
少なくともStateパターンからは外れています。また、オブジェクト指向プログラミングは配列の取扱について特別な何かを提案している手法ではありませんので、配列(表)を使うことが「厳格で純粋なオブジェクト指向」に則っているかと言うと微妙です。


【余談ですが】
では、使うべきでなはいかと言うとそうではないです。
オブジェクト指向プログラミングを使うことでメリットがある時はたいへん多いのでどしどし使うべきですが、オブジェクト指向は万能ではないので使えない時まで無理して使うのは愚かと思います。(MVCも同様です。)

オブジェクト指向プログラミングもMVCも、なんらかの目的(主にメンテナンス性や再利用性)を満たすための手段です。オブジェクト指向に拘ってメンテナンス性を劣化させては本末転倒です。「手段のために目的を選ばない」のは、学習や研究時だけに限定しておくことをお勧めします。
手段自体を学んだり研究したりすることが目的の時はもちろん手段重視でOKですし、今回のようなテーマはたいへん興味深いです。

投稿2017/02/25 02:31

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mightyMask

2017/02/25 11:41

となると、駒ごとのインデックス番号はModelの方の歩クラスなどで定義すると言う事ですよね。 駒毎のインデックス番号の定義などをModel側でしてしまうと言う事は、本来Viewがするべき処理をModelがしてしまっていると言うことにはならないでしょうか。
Chironian

2017/02/25 12:25

駒の種類を決めるのはモデルですね。ですから駒に通し番号を振るのもモデルの仕事です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問