[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[jfriends] データベースに格納するデータオブジェクトに持つ機能(Re: CADのクラス構造)
In article <9909010924.AA12959@xxxxxxxxxx>
Kazuya Maebashi wrote:
>だからといって、drawをShape以外の所に置いてしまうと、
>
>・Shapeの各サブクラスのデータメンバは、全部publicにするかア
> クセサを付けるかして「まる見え」にしなきゃいけない。
データベースに格納するデータであるからにはそのデータに対する(直接
/間接を問わない)操作(参照)は行えないとまずいですね.
draw()を使わないアプリケーションもあるという話なので、そういう人
にとってはdraw()だけが公開されていても何もできないことになります.
>・いざ描画するときには、長〜いelse ifの連なりで、いちいち
> instanceofでクラスを調べるの?
>
>ということになっちゃいます。これはこれで悲し過ぎます。特にふたつめ。
draw(Shape)というメソッドの実装が一つしかなければそうなりかねませ
んね.
>># ShapeにはDrawインターフェイスの実装クラスを返すfactory methodを
>># 用意しておけばよいのでは無いでしょうか.
>># そして、描画処理では
>># shape.getDraw().draw2DScreen(....);
>># shape.getDraw().draw3DScreen(....);等
>>Drawインターフェイスに新しい空間への描画機能が追加されるなどの拡
>>張を施しても、逆に機能を削除しても、Shapeには影響は無いですね.
>>でも、インターフェイスが変われば、Shapeのサブクラス数に相当する
>>Drawの実装クラスの変更/再コンパイルは結局必要ですが.
>
>勉強になります。
>
>これだと、DrawをShapeと独立して自由にいじれますが、
>
>「そもそも描画するかどうかもわからんのにShapeにDrawを入れるべきか」
>
>という点からすると...
>
>これが良いと思うわけでもないのですが、私の案としては、
>
>・ShapeRunTimeというabstractクラスを作って、そのインスタンス
> をShapeインスタンスが保持するようにする。
>・ShapeRunTimeを継承して、ShapeRunTimeForDrawerを作り、
> 「drawするアプリケーション」では、Shapeにそいつをくっつけ
> ておく。他のことするアプリケーションは、それぞれ
> ShapeRunTimeForXXXXを作る。
>・「drawするアプリケーション」は、ShapeRunTimeをダウンキャス
> トして使う(ここが美しくない)。
>・ShapeRunTimeForDrawerには、abstractなメソッドとして、
> draw()を入れておく。ShapeRunTimeForDrawerを継承して
> LineRunTimeForDrawerなどを作る。draw()の実装はそこに書く。
これではデータベースに格納されたオブジェクトが持っている
ShapeRunTimeのオブジェクトによって、各アプリケーションが使いたい
機能を持っていたり持っていなかったりします.
# Shapeに持たせてしまっては...
特定のアプリケーションだけが使う機能は特定のアプリケーションが実
装すればよいと思います.
つまりはShapeをwrapするオブジェクト、またはShapeを渡すメソッドと
してですね.
# この場合Shapeオブジェクトの型によって、実際に使うDrawer
# (やXXXX)の実装を切り替えないといけないので、instanceofが必要に
# なってしまう.
で、Shapeに持たせるのではなく生成して返すようにしておけば、その
interfaceのインターフェイス(と返すべき実装クラスの実装)が変わって
も大丈夫です.
この場合は、Shapeのサブクラスが実際に使うクラスを決めるので
instanceofは不要です.
interfaceにない機能は呼び出せませんが、必要になった時点で
interface(と実装クラス)を変更してもよいはずです.
drawは標準的でないから不要だとする設計であれば、今までのRDBMSと同
じように、Shapeは座標などのデータのみのクラスとしてdraw()を含む全
ての操作はアプリケーション側で用意せざるを得ないでしょうね.
可能な操作のインターフェイス型さえ決まっていれば、上に書いたよう
なfactory methodを使えて、キャストやinstanceofを全く使わずに実現
出来ますが.
非常に分かりにくい文になってしまったのでまとめて言い直します.
私は、こういうのを用意して、
interface ShapeFunction {
public void draw2D();
public void draw3D();
public void otherXXXX();//その他の汎用的そうな機能?
}
abstract class Shape {
abstract ShapeFunction createShapeFunction();
:
}
otherXXXXの有無はどうでもいいですが、
:
shape.createShapeFunction().draw3D(); // 通常
:
otherYYYY(shape); // 特殊な操作の場合
:
を使う.って事がいいたかったのです.
使わないメソッドがShapeFunctionの実装クラスに存在することもありま
すがそれは問題視することもないと思います.
前橋さん案は、
interface ShapeRunTime {
}
interface ShapeRunForDraw2D extends ShapeRunTime {
public void draw2D();
}
interface ShapeRunForDraw3D extends ShapeRunTime {
public void draw3D();
}
interface ShapeRunForXXXX extends ShapeRunTime {
public void XXXX();
}
で、使う時にShapeRunForDraw2D/3D/XXXX等にキャストが必要というパタ
ーンですね.
Shapeが上記のどのinterfaceを実装したクラスを返すかが(利用者に)わ
からないのが問題かなあ.って事がいいたかったのです.
それで、このときもし自分の使いたい機能の実装クラスを付け直したり
するくらいなら、Shapeは上記interfaceの存在を知らない方が良い=単な
るデータクラスとする設計で充分ですよね.(また変な文)
あああ.伝わるか不安.まさに乱文ですね.すみません.
──────────────────
木下 信@イデア
──────────────────