Flex、AIR、Java、Androidなど

Posts Tagged ‘デザインパターン

21 1月, 2009

Strategyパターンの理解

Posted by: tachibana In: プログラミング

※この記事は私が本を読み、頭で考えたことを将来完全に理解してから見直して笑ったりするためにそのまま羅列したものです。故に間違った理解や意味不明なこともたくさん出てくると思います。プログラミングを教えるような立場の方には有益かも(笑)?
Strategyパターンの理解
説明を見るなりこれは魅力的だと思った。要は判定材料と判定結果は常に変わらず、それを判定するアルゴリズムのみを分けて実装し、そこを入れ替え可能にしようとする考え方。
判定アルゴリズムは基の抽象クラスをimplementするのでインスタンス化はクラスに依存しない。
やはり将来的に拡張するであろう箇所は前もって決め、抽象クラスを継承する形で実装するのが良いだろう。
そしてそれらのクラスを使う時はスーパークラス型を使うこと。
これが一番大事。
自分なりの結論:

プロジェクト内である判定材料を比較し結果を出すような場合は比較する部分だけを分離してクラス化し、委譲によりしょりをまかせる。これによりその部分の実装を変えたり、そっくり入れ替えたりということが簡単にできるようになる。

コメントは受け付けていません。

13 1月, 2009

Bridgeパターンの理解

Posted by: tachibana In: プログラミング

※この記事は私が本を読み、頭で考えたことを将来完全に理解してから見直して笑ったりするためにそのまま羅列したものです。故に間違った理解や意味不明なこともたくさん出てくると思います。プログラミングを教えるような立場の方には有益かも(笑)?
Bridgeパターンの理解
一つのパッケージの中に機能のクラス階層と実装のクラス階層が混在することは当然考えられる。
ただ、この分け方がよく分からん。もともと再利用したいパーツが機能のクラス階層と実装のクラス階層に分かれていた場合、機能のクラス階層には実装のクラス階層のクラスはまだ登場しない。まあ継承されるメソッドや変数が定義されているだけだろう。
そこに新たにクラス階層との結びつきを定義するのがBridgeパターンか?
ここでは、機能のクラス階層のトップがそのクラス型の変数をもち、コンストラクタで初期化している。しかしこれだと既にこのクラスのコンストラクタを引数無しで使っているクラスがあったらそれは実装を大幅に変更する必要があるんでないかい??
まあそれは置いといて、初期化したクラスの抽象メソッドの定義はその初期化したオブジェクト自身の抽象メソッドに結び付けている。このままでは何の処理も行われないよね?
ここでのに機能のクラス階層と実装のクラス階層の各役割が重要なのか?
機能のクラス階層は渡されたオブジェクトを格納し、それのメソッドを利用し働く。メインクラス上には機能のクラス階層のクラスが置かれ、それのメソッドにアクセスがそのメソッド内で既に初期化さえている実装のクラス階層のクラスのメソッドを呼ぶ。サブクラスはインスタンスもsuperで、単に新たなメソッドを付け加えただけ。
利点がよく分からん。
クラス図を見ると例えば既に実装のクラス階層があり、そこに新たにそれとは別な機能(それを利用するが)をもった階層を展開したような時にはその階層と既にある実装のクラス階層を結びつける際、スーパークラスのコンストラクタないで実装を行えばサブクラスはスーパークラスのコンストラクタを呼ぶ実装をすればそれだけでその実装のクラス階層と結び付けられる、ということがBridgeパターンなのか?
書いてあった。こうやってクラスが綺麗に分かれていたら拡張はかなり楽になる。結びついているのは機能のクラス階層のトップのコンストラクタだけだから。その他は意識する必要がない。こりゃええわ。ここがポイントだ。
自分なりの結論:

プロジェクト内には具体的に仕事をするクラス(基本的にあるクラスを継承し、少なくとも抽象クラスではないクラス)の階層と、手続きの内容を定義した抽象クラスと、それを実装するクラス階層が存在する。また、これらは意図的に分けるようにしなければならない。この際は機能のサブクラスのサブクラスが実装のクラスのサブクラスのサブクラスの・・・を実装しうんぬんというようなことはやってはいけない。実装を行うのは継承のトップにあるクラスが、トップにあるインターフェースを実装するようにする。また、この際は実装のクラスを継承するのではなくコンストラクタ内でインスタンス化し処理を実装のクラスに委譲する。

コメントは受け付けていません。

13 1月, 2009

Abstract Factoryパターンの理解

Posted by: tachibana In: プログラミング

※この記事は私が本を読み、頭で考えたことを将来完全に理解してから見直して笑ったりするためにそのまま羅列したものです。故に間違った理解や意味不明なこともたくさん出てくると思います。プログラミングを教えるような立場の方には有益かも(笑)?
Abstract Factoryパターンの理解
これまではパッケージ内のクラスはメインクラス、又はその他のクラスに継承されたりimplementsされたりしていた。Abstract Factoryパターンではfactoryパッケージ
内のクラスを更に細かく分割。細かいアイテムを作るクラスも抽象メソッドだが、それもさらにスーパークラスをもつ。←抽象メソッドをextendした抽象メソッド。
また、このサブクラスではスーパークラスの抽象メソッドが定義されていないので、サブクラスを継承したクラスが大元の抽象メソッドを実装する必要がある。
それらの部品を管理するクラスが実装するのは、新たなオブジェクトをコンストラクタで生成、それに新しいアイテムを追加するメソッド(渡されるのは上記大元の抽象メソッド型)。そして出来上がったものをtraceするメソッド。最後に上記大元クラスによって定義され、そのサブ抽象クラスで実装されなかったメソッドがここで定義されている。※このクラスは大元クラスを継承もimplemetもしていない。。
それら全てを管理するのがFactoryクラス(抽象クラス)。抽象メソッドは渡された文字列をもとにクラスを探し、それを自身にキャストしインスタンス化したオブジェクトを返す。
さらに部品のサブクラスやそれらを管理するクラスを返すメソッドも抽象メソッドとして定義。
なぜFactoryはnewじゃなくgetGactory()?←抽象メソッドなのでnewできない。
実際に使うクラス。Factoryクラスが継承され、オブジェクトを返すメソッド(スーパークラス上で抽象メソッドでない)とFactoryクラスの抽象メソッドを定義したクラス。部品を返すのは引数を渡しnewされた部品のサブクラスを継承し、大元のクラスの抽象メソッドを定義したクラス。
実際に使われるクラスはインスタンス化された時にスーパークラスも初期化される。それにより渡されたオブジェクトのIteratorも作成されるのであとはwhile(it.hasNext)・・・でまわす。これがメインクラスに存在することぬいなる。尚、このクラス内では部品をつくるクラスは大元のクラスの型に代入され、それのメソッドにより動く。
やはりこれもメインクラスをいじらずに実装を変えられるのと、既にあるAbstractFactoryパターンを用いた部品郡を新たに実装する際には時間の短縮ができ、管理もしやすくなる。

コメントは受け付けていません。

11 1月, 2009

Builderパターンの理解

Posted by: tachibana In: 未分類

※この記事は私が本を読み、頭で考えたことを将来完全に理解してから見直して笑ったりするためにそのまま羅列したものです。故に間違った理解や意味不明なこともたくさん出てくると思います。プログラミングを教えるような立場の方には有益かも(笑)?
Builderパターンの理解
まずメインクラスがあり、メインクラスがやりたいことは2つの異なるオブジェクトの生成。その際、オブジェクトの生成はBuilderクラスのサブクラスが行う。
メインクラスがオブジェクトを生成したい時は条件により違う処理が必要。条件によりサブクラスをインスタンス化しDirectorクラスに渡す。あとはメインクラス上ではサブクラスのインスタンスを渡されたDirectorクラスのメソッドでもってインスタンスが生成される。
Directorのコンストラクタの引数にはBuilderクラスが。なのでサブクラスを親クラスに代入するいつものパターン。これにより依存しない関係となる。サブクラスであれば親の抽象メソッドが定義されているのであとはDirectorクラスが共通のメソッドで持って処理を行う。
これだと新たな種類のBuilderのサブクラスを実装する必要がでてきた時も設計を変えるのはメインクラスだけでよい(条件を追加するだけでよい)。Directorクラスがなかった場合はサブクラスが独自の仕様を持つことが可能になり管理が難しくなる。
ものをBuildするのはbuilderクラスだということが重要。
自分なりの結論:

分かりにくかったので料理で例える。
例えばボタンを押せば冷奴と湯豆腐を作れる機械をプログラミングしたいと仮定する。この際の手順は命令役(機械の押されたボタンによって冷奴か湯豆腐のレシピを選択し、豆腐を送る)と、レシピ管理役(冷奴と湯豆腐のレシピを管理している)に分ける。処理の流れは冷奴のボタンが押されたとき命令役はレシピ管理役に豆腐と冷奴が注文されたという情報を渡し、作れと命令する。レシピ管理役は冷奴のレシピを取り出し、その通りに料理し返す。こんな感じ。こうしておくことで豆腐をいいものや安いものに変えたり、マーボー豆腐をメニューに加えたりということも簡単にできる。
だめな例は、命令役とレシピ管理役を置かず、冷奴係と湯豆腐係を置くこと。こうしてしまうと豆腐を変えようと思った時には全員を集めて通知しないといけないし、新しくマーボー係を入れても豆腐をどこから仕入れるかから教えないと(プログラミングしないと)いけなくなる。豆腐がどれかなどとなどにこだわらず、ただ渡された豆腐にレシピ管理役に言われた通り料理せよというのが一番上手な管理方法となる。

コメントは受け付けていません。

09 1月, 2009

prototypeパターンの理解

Posted by: tachibana In: プログラミング

※この記事は私が本を読み、頭で考えたことを将来完全に理解してから見直して笑ったりするためにそのまま羅列したものです。故に間違った理解や意味不明なこともたくさん出てくると思います。プログラミングを教えるような立場の方には有益かも(笑)?
Prototypeパターンの理解
なんで= new Manager使うのか?
これまでのパターンはインターフェースをextendなりimplementしたクラスを、メインクラス上でそれらのスーパークラス(extendの際は)であるクラスに代入していた。prototypeパターンの場合のクラスの関係はManagerクラスは何もextendもimplementもせず、動くメソッドをもっているだけ。→抽象クラスではない(抽象クラスをextendする可能性もあるか? or してはいけない理由があるのか?)。
この場合、Managerクラスの働きはそれ自身に(key、Obj)の形のハッシュを置き、それのメソッドに引数が渡されcloneされようとした際にはkeyからハッシュを舐め、それをProductインターフェースが持つメソッドに委譲しProductを返す。
ちょっと待った。cloneというメソッドはJavaのクラスライブラリにすでにあるんだよな。<自分自身かサブクラスからしか呼び出せない。
サンプルプログラム。Managerクラスにはkeyとして与えられた文字列に対してあるクラスのインスタンスを返すような連想配列が置かれる。後に生成されるインスタンスは型は全て同じ。だが、内容は異なる。そして全て同じインターフェースをimplementしている。それにサブクラスを代入。代入はnewでインスタンス化されるのではなく、あらかじめmanagerのメソッドが行う。
Prototypeされたクラスはmanagerクラスによりメインクラスにkeyとともに初期化(インスタンスが存在するようになる)され格納される。即ち、managerを使い新たにオブジェクトを存在させる手順は、newしているのではなく連想配列に格納されたインスタンスを返しているだけである。これは自分にとって新しい。
もしmanagerクラスがなかったらどうなる?

まずクラスは毎回インスタンス化され始めて使えるようになる。その際コンストラクタによりある程度のカスタムは可能だが、あまり複雑なものは利用できない。
大切なのは、再利用されるパーツとしての価値を考えたとき、そのパッケージ内のクラスが他のクラスに依存しないこと。そのまま他のプロジェクトにimportされた時でも引数を付けて呼ばれた際には常に同じ動作をするよう設計されていること。その際にはProductインターフェースの存在は必須となる。managerはkeyによりProduct型のインスタンスを返し、ProductインターフェースはCloneableで、複製を行う抽象メソッドを定める。
自分なりの結論:

生成のたびにわざわざクラスからインスタンス化する必要がなくcloneでもよいオブジェクトや、ユーザーの任意の操作により変更されたオブジェクトを複製したい時に使う。通常インスタンス化されたオブジェクトを返すためにはその為のメソッドを用意する必要があったり、それを受け取るために受け取る側でも変数を定義してやる必要があったりでややこしい。このような時はCloneableを便宜上実装したインターフェースを作る等し、実際に仕事をするクラスにはそれを実装させる。ここでは、複製されたオブジェクトを返すメソッドの定義が実装するインターフェースにより義務付けられている。一つの親クラスを継承した何種類かのクラスがあり、それらのインスタンスを連想配列に保管しいつでも返せるようなクラスを用意しておけば、インスタンス化と同時にそのクラスにインスタンスへの参照とキーを登録するといつでもインスタンスを得ることができる。ここで重要なのは登録されたインスタンスは親インターフェース型の変数であり、連想配列に登録されているのは値ではなく参照だということ。この参照先を新たな変数に代入することでコピーが行われ、新らしい変数が生成されることとなる。

コメントは受け付けていません。

Categories

 

2017年9月
« 4月    
 123
45678910
11121314151617
18192021222324
252627282930  

About

Author: tachibana

  • ちょっとしたことはTwitterに書いています。こっちはアプリの公開等の時に更新されます。
  • 最近はもっぱらJavaとObjective Cです。AS3は飽きました。
  • スクリプト言語ではPerlが好きでしたが最近はGAE/Jで何でもやってます。
  • Linuxは自宅サーバー建てるのがやっとのレベルです。前の会社で何日も徹夜してやったのはいい思い出です。
  • アプリへのご要望などご意見等ありましたらお気軽にご連絡下さい。

Alternative content here