ire0014のブログ

IT、自己啓発、ゲーム関連の事を書きます。

デザインパターン(TemplateMethod)

概要

デザインパターンって良いなと思う場面に遭遇したので紹介します。

やりたかった事

似ているけど、別の処理が2つありました。処理Aと処理Bとします。その2つの処理には共通部分もあったので共通の処理が作ってありました。今回処理Bの機能追加をしたかったのですが、共通処理の部分に機能追加する必要があったので、処理Aにも影響が出る!まずい!となりました。
例えると、ロボットがいて、本を買いに行かせるプログラム(処理A)と、飲み物を買いに行かせるプログラム(処理B)があって、どちらもサイフにお金をいれて手に持つというプログラム(共通処理)を使っているのですが、今回飲み物のお店がポイントカード制になったので、飲み物を買いに行く時はポイントカードをサイフに入れて持つという機能追加が必要になったのですが、共通処理を修正すると、本を買いに行くプログラム(処理A)も動作確認しなきゃいけないし、今まで上手く動いていたものが壊れたらやばい!なるべく共通処理には手を入れたくないなーと思いました。

プログラム

処理A

共通処理読み込み
動作 本を買いに行く{
 財布用意()
 指定した場所に行く(行き先:本屋)
 指定した物を買う(買う物:本)
 指定した場所に行く(行き先:家)
 読む
}

動作 読む{
 # 省略
}

処理B

共通処理読み込み
動作 飲み物を買いに行く{
 財布用意()
 指定した場所に行く(行き先:本屋)
 指定した物を買う(買う物:本)
 指定した場所に行く(行き先:家)
 飲む
}

動作 飲む{
 # 省略
}

共通処理

動作 財布用意{
 財布取り出す
 お金をサイフに入れる
 # ←ここに「動作 飲み物を買いに行く」から呼ばれたときにだけ
 #「ポイントカードを入れる」という処理を足したい
}

動作 指定した場所に行く(引数){
 引数の場所に行く
}

動作 指定した場所に行く(引数){
 引数の物を買う
}

動作 指定した場所に行く(引数){
 引数の場所に行く
}

やりそうだったこと

でもまあ、共通処理いじるしかないか。飲み物買いに行く時の処理をif文で分ければ、まぁ壊れて大変な事にはならないでしょう。

修正前

動作 財布用意{
 財布取り出す
 お金をサイフに入れる
}

修正後

動作 財布用意{
 財布取り出す
 お金をサイフに入れる
 if(飲み物を買いに行く場合だったら){
  ポイントカードサイフに入れる
 }
}

コレでよし。と。よくないわ!

より良い方法

オブジェクト指向的に書いてあると、それぞれの処理はクラスのメソッドとかになっているわけで、そうなると継承という技が使えるのです。それぞれの「共通処理読み込み」が「インスタンスの生成」みたいな感じになるのですね。
要するに共通処理をそれぞれの処理のところで独自に機能追加できるのです。今やりたい事そのままじゃないですか!

上記の共通処理は修正しないで、処理Bを修正
処理B修正後

共通処理読み込み
動作 飲み物を買いに行く{
 財布用意()
 指定した場所に行く(行き先:本屋)
 指定した物を買う(買う物:本)
 指定した場所に行く(行き先:家)
 飲む
}

動作 飲む{
 # 省略
}

動作 財布用意(){
 もともとの財布用意に書かれていた動作は使ううえで
 ポイントカードサイフに入れる
}

えっ!コレだけ!すごい!
という事で、共通処理はいじらず、処理Bだけいじって、処理Aには絶対に影響がない形で機能追加できました。良かった。

まとめ

つまりオブジェクト指向の継承使っただけなのかもしれませんね。共通処理では枠組みや確実に共通な部分だけを作っておいて、それぞれ使うところでそれぞれ用の機能を追加していくという作り方(デザインパターン)を、TemplateMethodパターンといいます。デザインパターンすごい!勉強したい!すれば良いよ!と思いました。
というか今まで知らなかったという事は自分がどれだけひどいものを作り続けていたのか!と思うと申し訳ない感じです。
色々なデザインパターンを知った上で、ちゃんと設計してからものをつくっていきたいですね。
というか技術的な記事を書きたかっただけなんじゃないかな。

サイト「TECHSCORE デザインパターン
http://www.techscore.com/tech/DesignPattern/index.html/

書籍「増補改訂版Java言語で学ぶデザインパターン入門」