kr_ryo 徒然日誌 <2005年12月4日分>

三國志製作記122〜デザインパターンの威力〜

外は冷たそうな雨です。しかも明日には雪が降るという予報です。すっかり寒くなりましたね〜{{(>_<)}}ただいまの室温は8度です(~_~;)夏には40度近くなるのに、冬は0度近くです。日本の四季を感じさせます{{(>_<)}}今年は暖冬の予報ですが、やっぱり冬は寒い!街はクリスマスツリーはじめイルミネーションがあふれています。11月からクリスマスな風景だと、なんだかクリスマスというより冬のイメージだけになっているだけのような気もしますが…(^^;A

さて、三國志製作はデザインパターンの威力のおかげで快調に進んでいます(^O^)いやあ、改めてデザパタのすごさがわかりますね〜恣意的になりやすいオブジェクトが、きちっと役割のあるオブジェクトになってくれるので、ある流れを作れば、次から次へと流れを量産できてしまいます。手続指向だと、共通動作をサブルーチン化するため、どうしてもサブルーチンに合わせた作りになってしまいます。ところがデザパタだと、流れは共通でも、中身はまったく違っていてもいいので、思いが表現しやすくなります。しかも当然同じ内容なら再利用できます。

もちろん中身が違っていいなら手続指向でも当然できますけど、それは基本的には、中身が同じ内容を含めて違う流れは違う流れとしてまったく別に、二重に作ることを意味します。2つ作るわけです。それは無駄だというわけで、同じ部分を共通要素、サブルーチンとして別出しします。これが使えるサブルーチンだと、使う方もそれに応じる、合わせにかからないといけなくなるわけです。そのうち、流れが増えていくと、少し違う要素の組み合わせばかりになってきます。そうすると、メインルーチンは少しで、サブルーチンばかりで作ることも考えられます。

で、その流れの洗練されたものがオブジェクト指向で、さらにそれを洗練したものがデザインパターンです。オブジェクト指向ではメインルーチンがなくなります……もちろんJavaのMeinオブジェクトのように、名前からもメインルーチンになりやすく、実際巨大メインルーチンを作ってしまうこともよくありますが、そうでないのがオブジェクト指向です。しかもサブルーチンに相当するオブジェクトのメソッドすら、中身はたった1行なんてことがよく…むしろほとんどくらいに…あります。

たとえば武将の名前を表示させる、そういう場合、武将の名前を得る機能は、武将オブジェクトにあると考えるのが自然です。そこで、呼出元はID番号で武将オブジェクトに名前を問い合わせるのに、busyo.name_ID(ID)と書くだけでいい、という設計にしています。実際はbusyo.と.(ピリオド)を打てば、nameなりseijiなりがDelphi側でリスト表示してくれるので、より一層楽になります。自分で設計した武将オブジェクトの機能が、ピリオドを打つだけで呼び出せるわけですから、便利です(^O^)そのname_IDメソッドの側は、中身は単に、result:=Tbusyodata(busyo[id]).nameとたった1行書かれているだけなんです。実は、この1行を書くのが邪魔くさく、ピリオドでname_IDを呼び出したいがためにそうしてるんですけどね(^^;A

私も最初は、これくらいならそう書いてもいいんじゃないか?という気もしましたが、これこそがデザインパターンに沿った作りだったりするのです( ̄^ ̄)実は武将オブジェクトと、武将データオブジェクトとが別にあるのです。で、武将オブジェクトには武将データがありません。単に生成して管理して呼び出すだけです。これはFactoryMethodパターンだったりするのです。武将データは単にデータを持っているだけです。考えてみれば、これだけで武将データベースになっているんですね。オブジェクト指向のカプセル化を徹底すれば、武将データも直接は呼び出せないようにした方がいいのです。そうすると、このたった1行だけでも武将オブジェクトによって呼び出してもらう方がいいんですよね。

こんな風に管理されていないオブジェクトだと、外部のオブジェクトから呼び出す際に、そのリクエストに応じてデータの側がいっぱい加工されたりしてしまいます。そうするとその加工に合わない呼び出し方をしたいときに、加工を戻したり、別の加工をしたりする別の方法が必要になり、それが繰り返されると、そういった加工は呼出元でやってくれい、ということになってしまいます。だいたいデータはデータで、加工は加工と別にすべきです。ただ、繰り返し使う加工は別に用意しておきたい。そういう場合、データオブジェクトと管理加工オブジェクトを用意すればいいわけです。

そうして、データオブジェクト(武将データオブジェクト)は直接外部から呼び出せず、汎用性ある加工はデータ管理オブジェクト(武将オブジェクト)に、データを呼び出すついでに加工するよう用意しておくという発想になるわけですね。FactoryMethodパターンはデータ生成だけでなく、管理機能を持たせることもできるわけで、その管理機能がどんどん拡張されていって、便利になっています(^O^)楽が進むと、さっきの名前呼び出しだけでも、IDで武将の名前を呼び出したい場合、ポインタで武将の名前を呼び出したい場合の2種類、逆に、名前からIDを検索したい場合、名前からポインタを検索したい場合という合計4種類も用意してしまいました(^^;AさらにはIDからポインタを呼び出す場合とか、ポインタからIDを呼び出す場合とか、まさにデータベースです。

データベースと考えれば、別に中身が1行だけであっても全然問題ないわけですね。むしろ、呼び出す方のリクエストにできるだけ応じていく方がいい、使いやすく作りやすくしておく方がいいわけです。こうやって使っていくと、以前もお話したように、C言語最大の難関といわれるポインタもあっさり理解できてしまいます(^^;A特にオブジェクト指向では、オブジェクト自体がポインタで指示するわけですから、むしろポインタがオブジェクトそのものという発想に近くなってしまいます。ポインタとは結局メモリアドレス、住所データですから、藤原家がその住んでる場所で一条家(京都の一条)や加藤家(加賀国?)と呼ばれるようになっていったように、場所、住所が本体を意味する、意外と自然な発想だったのです。

当然アドレス、住所だけでは身動きが取れませんから、型キャストと呼ばれるラッピングをほどこす必要があります。型、つまりオブジェクトの原型であるクラスに、住所データを与えると、中身、エネルギーを吹き込むのと同じ感覚で、オブジェクトとして使えるようになります。それが、Tbusyodata(←クラス)であり、busyo[ID](←アドレス。これは、IDでポインタを呼び出している)であって、エネルギーを吹き込むとは、先程のTbusyodata(busyo[id])なのです。うう、ちょっと難しいかもしれませんが、要は「型(ポインタ)」でオブジェクトが使える、というだけなんです。ほんで、それすら邪魔くさいので、管理オブジェクト経由で利用しよう、それがbusyo.name_ID(ID)と、そういうわけなんですね(^-^)

そんなデザパタ&オブジェクト指向の威力の恩恵を受けながら、1機能1機能づつ搭載していってます(^-^)SWGおなじみのランダム順番も移植し、コンピュータ指向ルーチンの原型もできました。ちゃんと回ってます(^^;やっぱり土台がしっかりできていないと厳しいですね。1機能載せるごとに重くなり、2機能載せたら傾き…では怖くて作ってられません(*_*)手続指向はメインルーチンの上にどんどか載せていくイメージで、デザパタは共通規格の部品を組み合わせて量産していくイメージです。手続指向だと、メインルーチンがよほどしっかり広く汎用的に設計していないと、載せている機能の重みで倒れてしまいます……なんだか最近話題の話に似ているような…(^^;A……単なるオブジェクト指向だと、これはこれで乱雑に組み合わせるだけになりがちで、デザパタでようやく美しいデザインのもとに設計できる、というような感じですね(^O^)

それにしても、このままいくと年内完成が夢ではないくらい進みそうです(^O^)UIはデザパタでできているのでいつでもどんな感じの追加にも対応できますし、データはこれまた増えても増えても管理オブジェクトのおかげで取りまわしが楽です。こうなると後はルールだけですけども、武将の個性化について簡単ながら、なるほど!と思うような方法を2つほど思いつきました(^O^)内政も細かくはないですけども、作っているうちに、システムに応じてこうすれば統制しつつ自主性がある、というような方法を思いつきました(^O^)いやあ、進めば進むもの、残る未検討項目は戦闘シーンだけになりましたが、これもモデルがはっきりしましたんでシミュレーションは容易…

…となると、検討すべき内容がなくなって、製作記が書けなくなってしまいますね(^^;;;ま、製作記がなくたって、これをご覧の皆さまなら、早くできた方がいいと思ってくださるに違いない…(^O^;)

index

〔TopPage〕

このページへのリンクはフリーです。
このページについてのご意見、ご質問などは、kr_ryo_green@yahoo.co.jpまでお願いします。
Copyright 2005© kr_ryo All rights reserved.
訪問件数