ブログ「サイバー少年」

ブログ「サイバー少年」へようこそ!
小学六年生ごろからプログラミングを趣味にしている高校生のブログです。
勉強したことについての記事などを書いています。フリーソフトも制作、公開しています。
(当ブログについて詳しくは「ブログ概要紹介」を参照)

サイバー少年が作ったフリーソフトは「サイバー少年の作品展示場」へ

GoFデザインパターン解説 THE LAST

今回はGoFデザインパターン解説をします。

この前のGoFデザインパターンの記事「[GoF] クラスで表すパターン解説」で、
もう解説できるようなパターンが、Builderパターン、Bridgeパターン、ChainOfResponsibilityパターン、Proxyパターンぐらいしか残っていないと書きましたが、

今日はそのネタを使いきってしまおうと思います。
4つも書くのはしんどいんですけどね…。

あと、もうあんまり覚えてない…。

というわけで、今回の記事は、当ブログでのGoFデザインパターン解説記事としては最後になります。





Builder

Builderパターンという名前ですが、Builderという役割のクラスと、Directorという役割のクラスが活躍するので、
Builder-Directorパターンという名前のほうがいいんじゃないかと思いますね。

これは、あるオブジェクトを色々と操作したいというときに、操作をする側の処理をDirectorという役割のクラスに押し込んでしまう、というのがまずひとつです。

そしてミソなのは、その操作する内容を抽象化してしまうということです。


どういうことかというと、たとえばキャンバスに絵を描く処理を考えます。
このとき、実際にキャンバスに絵を描くクラスは、Directorとなります。

Directorはキャンバスとなるオブジェクトを直に持っているのではなくて、Builderというメンバを保持していて、Builderがキャンバスを持っているという構図にします。


Builderは、線を描くとか、円を描くとか、三角形を描くとか、色々な図形をキャンバスに配置するメソッド群を持っているクラスです。

Directorはどのような順番でどのような場所に図形を配置していくのかというのを担当しますが、実際にキャンバスに描くのは、Directorに要請されたBuilderとなります。


ここで、Builderを抽象クラスにしてみます。
色々な図形を描くメソッドは抽象メソッドにして、子クラスがどのようにそれを実装するかによって、

水彩画風の図形とか、油絵風の図形とか、鉛筆風の図形といったように絵の種類を変えられるようにします。


もちろん、図形を描く順番や位置を決めるのはDirectorであって、Directorがどのような絵を描くのか決めるのですが、Directorに与えるBuilderを切り替えることで、

同じ絵に対して水彩画や油絵などの絵の種類を設定できるようになるというわけです。


これを一般化すると、操作対象となるオブジェクトと、Director役のクラスと、Builder役のクラスがあって、

Builder役のクラスは実際に操作を行うので、操作対象となるオブジェクトとくっついているんですが、

Director役のクラスは操作する対象を知ることなく、抽象的なまま、抽象的な命令をしてそれを操作することができるということです。




ChainOfResponsibility

これは簡単ですが、すごく効果のあるパターンですね。

あるオブジェクトを処理したいとなったときに、オブジェクトの種類によって、処理を行うクラスが異なってくることがあります。

そんなとき、条件分岐で「このオブジェクトならこのクラス」とやっていると、オブジェクトの種類が増えたときに、条件分岐が色々なところにあると特に対応が難しくなります。


そこで、このパターンは条件分岐を無くしてしまおうという趣旨です。
条件分岐をなくそうというのは、GoFデザインパターンに総じて言える趣旨ですね。

どうするのかというと、Chainというくらいですから、処理を行うクラスを連結リストのように繋いでしまいます。

具体的には、処理を行うクラスに、自分が処理できない場合にオブジェクトを渡す次のクラスの参照を持たせます。


そして、まず一番最初のクラスにオブジェクトを渡して、一番最初のクラスがオブジェクトを処理できるなら処理して、もし対応できないものだったら、次のクラスに処理させて、

次のクラスにおいても、自分が処理できるなら処理して、無理ならば次のクラスに回すというのを繰り返します。


この方法を取れば、条件分岐の必要はありませんね。

ただし、すごく種類の多い条件分岐をChainOfResponsibilityパターンに落とし込んでしまうと、オブジェクトの処理に時間が掛かる場合があるので、
そういうのは控えたり、連結リストの順番を考慮しないといけません。




Bridge

記事「本「オブジェクト指向でなぜつくるのか」の感想、要約」で書きましたが、一般的なクラスの継承には、実装の継承とインターフェースの継承という二つの目的があります。

そして、それらがひとつの継承関係の列に混ざっているのはあまり美しいことではありません。


たとえば、抽象クラスAbXに対して、その実装としてクラスX1を継承させます。

ここでXに機能が追加されたクラスYを追加したいとなったときに、AbXを継承して抽象的なYクラスAbYを作るだけではなく、
X1を継承して、X1の実装を使うYクラスY1を作ったり、

もし、新たなAbXの実装としてクラスX2が作られたら、X2の実装を使うYクラスY2を作らなければならないというわけです。

つまり、似たようなクラスをいたるところに書かなければなりません。


これは、実装の継承とインターフェースの継承を、同じ列に入れていることが問題だから、これらを違う列に分けてしまえばいいだろうという発想がBridgeパターンです。


具体的には、実際に継承を使うのは実装の継承だけにして、インターフェースの継承は委譲で代用します。

つまりは、実装の継承関係による機能追加があったとしても、親クラスの実装よりも新たな実装が必要になることはないという条件はあるのですが、

クラスの実装の継承関係を構築しておいて、ルートとなるクラスに、自身の実装をするオブジェクトのメンバを保持させて、

委譲先をラップするような要領で、ルートとなるクラスはその実装を呼ぶようにするというわけです。


具体例がないと、この説明ではちっとも分からないかもしれないですが…。


要するに簡単に言えば、実際の継承の列は、機能追加の継承(実装の継承)だけにして、
機能の実装を行うクラスは委譲によって呼び出されるということです。

この委譲されるクラスを取り替えることによって、実装を切り替えることもできます。

これもなかなか便利なパターンです。




Proxy

Proxyパターンは、あるインスタンスを生成するのに大きなリソースが必要であるというときに使うパターンです。

その重いインスタンスを実際に生成しなければ行えない処理もあるにせよ、
パラメータの設定とか、今すぐインスタンスを生成しないと駄目というわけではない処理もあるはずです。

つまり、本当にインスタンスを生成する必要が出てきたときにようやくインスタンスを生成して、そのときにパラメータの設定とかも反映させてやればいいというわけです。


しかし、このようなインスタンスを必要になったとき生成する機能をインターフェースからは隠して、

まるで重いインスタンスを直接使っているかのようなインターフェースで、実際は必要になるまでインスタンスが生成されていないという使い方ができたら、修正が容易です。


そこで、Proxyとは代理人という意味ですけども、あたかも重いインスタンスの代理人のようなことをするクラスを作って、

そのクラスはパラメータの設定とかは自分でやるけど、実際に重いインスタンスを作らなければならなくなったら作って、それに処理させるという形にします。

これがProxyパターンです。
このパターンも便利ですね。




というわけで、サンプルコード無し、具体例もほぼ無しの、とんでもないクソ解説でしたが、4つのパターンの解説でした。

抽象的な説明ばっかりなのは、今までの当ブログでのGoFデザインパターンの解説記事にも言えることですが、本当に反省すべき点ですね…。

まあ、具体例を作るのって本当に面倒くさいんです。
許してください(←許されない行為)。


GoFデザインパターンしか私は勉強していないですが、GoFデザインパターンってもう若干古いみたいで、

GoF以外にも色々なパターンが考案されているみたいですね。

まあ、デザインパターンブーム到来のキッカケとなったのは、GoFだと思うので、その面ではGoFデザインパターンもなかなか凄いと思いますが。


最近のデザインパターンでホットなのは、非同期処理関連でしょうか。

C#とかにも、非同期処理のデザインパターンを使ったと思われるクラスライブラリがありますね。

こういうのも、機会があったら勉強してみたいですね。

tag: プログラミング オブジェクト指向 GoF デザインパターン クラス 継承 プロキシ 条件分岐 リスト 処理

コメント

コメントの投稿

トラックバック

トラックバック URL
http://cyberboy6.blog.fc2.com/tb.php/460-8bcc3486
この記事にトラックバックする(FC2ブログユーザー)

当ブログをご利用(閲覧等)になる場合は必ず「当ブログの利用規定」をお守りください。