Fillomino Player Architecture / System Design

機能外要求

システム分析の成果物を入力として、また機能外要求を踏まえて、分析オブジェクトを詳細化する。 このIterationで重要となる機能外要求は、

です。これらの要件とFrameworkの仕様を含めて、分析オブジェクトの詳細化を行った。

各分析オブジェクトの詳細化

Model Layer:盤面情報の管理

Puzzle Frameworkにおける、モデルの仕様は以下のようになっている。

jp.gr.java_conf.ktz.puzzle.framework.Model
オペレーションアクセス説明
lastModifiedPospublicユーザーにより変更されたセルの位置を返す。
isModifiedpublic盤面がユーザーにより変更されているかどうかを返す。
flushpublic変更された位置をリセットする。
getCurStateAtpublic指定された位置のセルの状態を取得する。
nextStateAtpublic指定された位置のセルの状態を次の状態に遷移させる。
prevStateAtpublic指定された位置のセルの状態をひとつ前の状態に遷移させる
createBoardpublic指定されたサイズの盤面を構築する。
initProblemAtpublic指定された問題レコードを盤面に割り当てる。
setProblempublic指定された問題を読み込み、盤面に反映させる。
containspublic指定された位置が盤面内かどうかチェックする。
isNumberAtpublic指定された位置のセルの状態が数字状態であるかどうかチェックする。
isSpaceAtpublic指定された位置のセルの状態が空白状態であるかどうかチェックする。
isTransitAtpublic指定された位置のセルの状態が遷移できるかどうかチェックする。
getHeightpublic盤面の高さを取得する。
getWidthpublic盤面の幅を取得する。
getSizepublic盤面のサイズを取得する。

Frameworkにおいて、このモデルをDecoratorのパターンを適用し、階層化することで、 モデルの責務を小さくするようにしている。階層化を容易にするため、 Frameworkでは、抽象クラスAbstractdecorationModeを用意している。

jp.gr.java_conf.ktz.puzzle.framework.AbstractDecoratedModel
オペレーションアクセス説明
nextStateAtSelfprotected指定された位置のセルの状態を次の状態に遷移させる。
prevStateAtSelfprotected指定された位置のセルの状態をひとつ前の状態に遷移させる
createBoardSelfprotected指定されたサイズの盤面を構築する。
initProblemAtSelfprotected指定された問題レコードを盤面に割り当てる。
lastModifiedSelfprotectedユーザーにより変更されたセルの位置を返す。
isModifiedSelfprotected盤面がユーザーにより変更されているかどうかを返す。
flushSelfprotected変更された位置をリセットする。
addModelpublicデコレート対象をModel階層の最下層に追加する。
getDecoratedprotectedデコレート対象を取得する。
isAvailableEventprotected指定されたStateEventCodeを受け入れることができるかどうかチェックする。

この仕様を元にフィルオミノにおける盤面情報の管理のRelationshipは、下図のような構成になった。

図:盤面情報の管理のクラス図
図:盤面情報の管理のクラス図

この図において、青く色図けられたクラスは、Frameworkに含まれるクラスである。 盤面の内部情報を管理するクラスBoardModelは、 ユーザーによる選択情報を管理するSelectionModelによってラップされていることを示している。

Model Layer:State

Frameworkの仕様に従って、状態遷移マネージャの実装を与える必要がある。 盤面の状態遷移は、空白から数字状態、または数字状態から別の数字状態、または数字状態から空白状態に絞られる。 選択状態は、既存の状態を選択状態でラップすればよいので、遷移マネージャには含めない。

図:盤面状態の遷移図
図:盤面状態の遷移図

Controller Layer:盤面状態の更新

盤面状態の更新の挙動は、Frameworkでは現在定義されていないため、フィルオミノ専用のものを定義した。 下この挙動に対して、下表のコンポーネントと責務を与えた。

jp.gr.java_conf.ktz.puzzle.fillo.controller.ChangeHandler
オペレーションアクセス説明
notifySelectionChangedpublic盤面の特定領域を選択する。
notifyInputOccuredpublic選択された箇所に数字を入力する。

フィルオミノでは、ChangeHandlerを実装したクラスFilloChangeHandlerを定義した。

下図は、このコンポーネントのRelationshipを示している。

図:盤面状態の更新のクラス図
図:盤面状態の更新のクラス図

また、Modelに対して送信するStateEventCodeを実現したValueオブジェクトChangeEventとNumberInputEvent の仕様を下表に示す。

jp.gr.java_conf.ktz.puzzle.fillo.controller.ChangeEvent
属性アクセス説明
TYPE_SELECTIONpublic選択イベントタイプ。
mEventTypeprivateイベントタイプ。
mIsActivePosprivateアクティブポジションダルかどうかを示すフラグ。
jp.gr.java_conf.ktz.puzzle.fillo.util.NumberInpouEvent
属性アクセス説明
mValueprivateアクティブポジションダルかどうかを示すフラグ。

ChangeEventやNumberInputEventは直接インスタンス化せず、Factory Method, ChangeEventFactoryを介して生成する。 このIterationの段階では、選択イベントと数字入力イベントのみを作成することができる。

jp.gr.java_conf.ktz.puzzle.fillo.controller.ChangeEventFactory
オペレーションアクセス説明
createSelectionEventpublic選択イベントを作成する。
createNumberInputEventpublic数字入力イベントを作成する。

ChangeEventを取り巻くオブジェクトやクラスのRelationshipは、下図のようになった。

図:Valueオブジェクトのクラス図
図:Valueオブジェクトのクラス図

Controller Layer:問題の読み込み

問題の読み込み挙動も、Frameworkでは定義されていないため、フィルオミノ専用の定義を与えた。 この挙動に対して、下表のコンポーネントと責務を与えた。

jp.gr.java_conf.ktz.puzzle.fillo.controller.ProblemLoader
オペレーションアクセス説明
loadProblempublic指定された問題を読み込む。

このコンポーネントの静的な構造とModelに対して送信するValueオブジェクト、ProblemInfoは frameworkで下表のように定義されている。

jp.gr.java_conf.ktz.puzzle.framework.ProblemInfo
属性アクセス説明
mFileNameprivate問題が保存されているファイル名。
mIndexprivateこの問題のインデックス。
mWidthprivate水平方向のセル数。
mHeightprivate垂直方向のピース数。
mRecordsprivate各セルのRecordを格納するList。

フィルオミノでは、このインターフェースを実現したクラスFilloProblemLoaderを定義した。

このコンポーネントを取り巻くクラスとの間のRelationshipは下図のようになった。

図:問題の読み込みのクラス図
図:問題の読み込みのクラス図

View Layer:画面の表示

表示の更新挙動は、Frameworkで定義されているが、Modelに対してViewが直接アクセスしていることや、 FrameworkのRendererの責務の重さに違和感を感じていたため、再設計した。 もとのframeworkでは描画情報をRendererが管理しており、実際の描画はRenderer#renderから RenderListener#renderへ処理を委譲させることで行っていた。 再設計において、盤面の管理とRenderListenerの管理を分離させることに主眼を置いた。 また、ただ指定された状態を描画するのではなく、直接Model等から状態を取得し描画するようにした。 新設計では、この描画全般を管理するクラスとしてRenderStrategyを作成した。 これに伴い実際に描画を行うクラスをRenderListenerからRendererに変更し、 Rendererの管理、探索を行うクラスRendererLocatorを作成した。

結果、この挙動に対して、下表のコンポーネントと責務を与えた。

jp.gr.java_conf.ktz.puzzle.fillo.view.RenderStrategy
オペレーションアクセス説明
renderpublic描画を依頼する。
getRenderedImagepublic描画したイメージを取得する。
installRendererpublic実際に描画を実行するRendererをRendererFactoryを介して登録する。
installDefaultRendererpublicBackgroundの描画を行うRendererをRendererFactoryを介して登録する。
setBackgroundpublicBackgroundカラーをセットする。
setSizepublic表示用のイメージサイズを変更する。
getBoardSizepublic表示用のイメージサイズを取得する。
setPieceSizepublic1セル区画のサイズをセットする。
getPieceSizepublic1セル区画のサイズを取得する。
calcPortToBoardPospublicスクリーンの座標からBoard条の座標に変換する。
getClipBoundspublic再描画が行われるClipping領域を取得する。

RenderStrategyでは、システム分析で抽出された責務に加えて、表示領域の作成や取得などの責務を加えた。

jp.gr.java_conf.ktz.puzzle.fillo.view.RendererLocator
オペレーション説明
lookup指定された状態の対応するRendererを検索する。
addRenderer内部テーブルに状態をキーとするRenderを登録する。
installRenderer実際に描画を実行するRendererをRendererFactoryを介して登録する。
installDefaultRendererBackgroundの描画を行うRendererを登録する。
jp.gr.java_conf.ktz.puzzle.fillo.view.Renderer
オペレーション説明
render実際に描画を実行する。

Rendererに対して与えるValueオブジェクトとしてframeworkにおいて、RenderEventが定義されている。 上述の設計変更により、Rendererの探索をRendererLocatorに変更した。 また、RenderStrategyにセットされているBackgroundカラーも渡すように変更した。

jp.gr.java_conf.ktz.puzzle.fillo.view.RenderEvent
属性アクセス説明
mLocatorprivate指定された状態に対応するRendererを探索するオブジェクト。
mGraphicsprivate描画先。
mBackColorprivateBackgroundカラー。
mBoundsprivate描画領域。
mStateprivate描画したい状態。

フィルオミノでは、描画全般の管理クラスとして、FilloRenderStrategy、 Rendererと状態とのマップを管理するクラスとして、FilloRenderLocatorを定義した。
これらのコンポーネントの静的な構造とRendererに対して送信するValueオブジェクト、は下図のようになった。

図:画面の表示のクラス図
図:画面の表示のクラス図

実際に描画を実行するRendererの実装はRendererFactoryを介して作成、登録する。

jp.gr.java_conf.ktz.puzzle.fillo.view.RendererFactory
オペレーションアクセス説明
installpublicRendererを構築し、RendererLocatorに登録する。

バックグラウンドを描画するRendererはRendererFactoryを実装した 抽象クラス, AbstractDefaultRendererFactoryを介して作成、登録する。 このFactoryは、デフォルトの登録処理が実装されており、 このメソッドの内部でRendererを作成するcreateRendererを呼び出す。 クライアントコードでは、createRendererをオーバーライドする必要がある。

jp.gr.java_conf.ktz.puzzle.fillo.view.AbstractDefaultRendererFactory
オペレーションアクセス説明
createRendererprotectedRendererを構築する。

フィルオミノでは、これらのクラスを実装した、 FilloStateRendererFactoryとFilloDefaultRendererFactoryを定義した。
RendererFactoryを取り巻くクラス間のRelationshipは、下図のようになった。

図:Java AWT/Swingとの連結部のクラス図
図:RendererFactoryのクラス図

View Layer:Java AWT/Swingとの連結部

マウスアクションやキー入力を統括させるため、FilloInputHandlerを定義した。 問題をロードした後、アクティブポジションを(0, 0)に動かす必要があるが、ProblemLoaderからは動かすことができないため、 インターフェースInputHandlerを下表のように定義た。FilloInputHandlerはInputHandlerも実装している。

jp.gr.java_conf.ktz.puzzle.fillo.view.FilloBoardView$FilloInputHandler
オペレーションアクセス説明
initActivePospublicアクティブポジションを初期化する。

また、FilloInputHandlerの静的構造を下図に示した。 黄色く色づけられたインターフェースは標準ライブラリに含まれるものを示している。

図:FilloInputHandlerのクラス図
図:FilloInputHandlerのクラス図

以上のコンポーネントをJava AWT/Swingと連結するコンポーネントは下図のように定義した。

図:Java AWT/Swingとの連結部のクラス図
図:Java AWT/Swingとの連結部のクラス図

設計モデルの動的側面

以上の詳細化により、各オブジェクトの動的側面は、分析オブジェクトから下図のように修正された。

ユースケース:表示の更新

図:Rendererの登録のシーケンス図
図:Rendererの登録のシーケンス図

図:表示の更新のシーケンス図
図:表示の更新のシーケンス図

ユースケース:単一区画の選択

図:単一区画の選択のシーケンス図
図:単一区画の選択のシーケンス図

ユースケース:数字の入力

図:数字の入力のシーケンス図
図:数字の入力のシーケンス図

ユースケース:問題のロード

図:問題のロードのシーケンス図
図:問題のロードのシーケンス図

prev : [システム分析] up : [目次] next : [テストケース]


© 2003, Kazuhiko TAMURA All rights reserved.

[W3C validator]