« やる夫がデザインパターンをやるようです 第7回 | メイン | SharePointとExtJS連携でデータシートビューフォームを自前でつくったよ!(EditorGridPanelの使い方) »



やる夫がデザインパターンをやるようです 第8回

やる夫がデザインパターンをやるようです 第8回をはてなブックマークに追加 やる夫がデザインパターンをやるようです 第8回をdel.icio.usに追加  Yahoo!ブックマークに登録 やる夫がデザインパターンをやるようです 第8回をGoogle Bookmarksに追加 やる夫がデザインパターンをやるようです 第8回をtwitterにポスト
≪第7回第9回≫

ワタシはC++からオブジェクト指向言語に触れたので、newしたインスタンスは必ず明示的にdeleteするという作法が体に染み付いております。スマートポインタなどを利用することもありますが、基本的にはアロケートした領域は自分で開放するのが当然であると思っていて、このことがワタシにとってファクトリの理解を阻むものだったのでは?と今では思っています。 今回のファクトリパターンはインスタンスをnewして返すものなので、開放はどこで行うべきかを意識する必要があるのですが、できればnewを押し付けたりしないで、自分でメモリのアロケート→開放を管理したいというのが当時ワタシが思っていたことでした。

とまぁ、ワタシのことはどうでもよいのですがやる夫の続きです。
インスタンスの生成くらいでごちゃごちゃ規制されたくないお
デザインパターンだかなんだか知らんが、
おいらのようなスーパーハカーに任せておけばプロジェクトは成功するお
        ノ L____
       ⌒ \ / \
      / (○) (○)\
     /    (__人__)   \
     |       |::::::|     |
     \       l;;;;;;l    /l!| !
     /     `ー'    \ |i
   /          ヽ !l ヽi
   (   丶- 、       しE |そ  ドンッ!!
    `ー、_ノ       ∑ l、E ノ <
               レY^V^ヽl 





   ふふーふーん♪コンストラクタをたくさん用意して
   みんなに「使いやすいっ」て言われるクラスをつくるお
   間口を広げておけばきっとたくさん釣れr使ってくれるお
           ____ 
        /⌒  ⌒\ 
.      /( ●)  (●)\ 
     / ::::::⌒(__人__)⌒::::: \ 
    |      |r┬-|     |  
     \       `ー'´     / 
    ノ            \ 
  /´               ヽ                 カ 
 |    l   l||l 从人 l||l      l||l 从人 l||l   カ    タ 
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、.     タ 
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒)) 
     ┌┬┬┐┌┬┬┬┐┌┬┬┬┐┌┬┬┬┐ 
  ,. - ''"| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ρ ̄`l 
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ノ ̄ 






   このまま続けちゃったらソースコメントに
   // やるお神光臨ktkr(よくやった。アーキより)
   なんてかかれちゃうお
         ___ 
       / ⌒  ⌒\  
      / (●)  (●) \ 
    /   ///(__人__)/// \ 
     |   u.   `Y⌒y'´    |
      \       ゙ー ′  ,/
      /⌒ヽ   ー‐    ィヽ
      / rー'ゝ       〆ヽ
    /,ノヾ ,>      ヾ_ノ,|
    | ヽ〆        |´ | 






<1週間後>
  バグの修正したらコンパイルがとおらなくなったお。。。
  おいらのクラスにさらにコンストラクタ追加したボケはだれだお。
  ::::::::  ::    ::     :::::  ::  :::
  ::::::  ::   ____   :::::  ::::  :::
  ::::::  :::: /  :::  \ :::   :::   ::
  ::::  ::::/   ::     \::  :::  ::
 ::::  /:::    ─    ─ \ ::  ::
 :::  |  ::   .(○)  (○)  | :  ::::
  :::   \     (__人__)  ,/ :  :::
  ::  ノ      ` ⌒´   \ :   :::
  /´               ヽ  :::
 |    l              \:::
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、.
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒))







<2週間後>
           ___
     ____,./      \ コンパイルを通したら
    ノ   /         \  新しいバグがいくつもでてきたお。。。
  /   /            \
 |     |::..           ...::::| 
 ヽ    `一ー――――-、;;;;::/`一ー―-、
  ヽ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒))







      / ̄ ̄\てめぇのアタマをデバグしてから出社しやがれ
    /ノ( _ノ  \  
    | ⌒(( ●)(●)
    .|     (__人__) /⌒l 
     |     ` ⌒´ノ |`'''| 
    / ⌒ヽ     }  |  |               ぺきょ
   /  へ  \   }__/ /             / ̄ ̄\ 
 / / |      ノ   ノ           / ●)) ((●\’, ・ 
( _ ノ    |      \´       _    (   (_人_)’∴ ),
       |       \_,, -‐ ''"   ̄ ゙̄''―---└'´ ̄`ヽ   て 
       .|                  ______ ノ    ( 
       ヽ           _,, -‐ ''"  ノ       ヽ   r'
         \       , '´        し/..     | J 
          \     (           /      | 
            \    \         し-  '^`-J 

<シンプルファクトリ>

というわけで、まずシンプルファクトリについてソースを含めて解説してみます。
// ファクトリ
class SimpleFactory {
    public Game createGame( String name ){
        Game gameInst = null;
        if( name.equals( "やるおの大冒険" ) ){
            gameInst = new ActionGame();
        }
        else if( name.equals( "ニコニコクロニクル" ) ){
            gameInst = new RPGGame();
        }
        // ほかにもたくさん。
        return gameInst;
    }
}

// ニコニコゲーム製作会社クラス
class NiconicoGameCompany {
    SimpleFactory fctryInst;
    // コンストラクタでファクトリをもらう。
    public NiconicoGameCompany( SimpleFactory param ){
        this.fctryInst = param;
    }
    
    public Game orderGame( String name ){
        Game gameInst;
        
        // ファクトリを使ってゲーム名を渡して返してもらう。
        gameInst = fctryInst.createGame( name );
        
        gameInst.prepare();
        gameInst.produce();
        gameInst.checkProduct();
        gameInst.package();
        return gameInst;
    }
}
ソースは上記のように書いてみました。一見するとファクトリは適宜インスタンスをnewして返すだけなので、自分でnewすりゃいいじゃんかと思うかもしれませんが、ソースのNiconicoGameCompanyクラス以外でGameクラスを扱うゲーム製作会社クラスがファクトリにnewを委譲してしまうことで、先に書いたやる夫のようなハマリ方はなくなります。
この使い方そのものはシンプルファクトリなどと呼ばれていて、SimpleFactoryが返すcreateGameの部分はスタティックにして使われたりすることがよくあります。

<ファクトリメソッド>

■ファクトリとプロダクト(工場と製品)
ファクトリメソッドは、
  1. ゲーム製作会社(:ファクトリ)スーパークラス(抽象クラス)を用意して
  2. これを継承するサブクラスで、インスタンスの生成を拡張してデザインされるものです。
ゲーム製作会社は、NiconicoGameCompany以外にもNyantendoGameCompany、SquareEnixoなどが考えられます。これらのゲーム製作会社がGameCompanyクラスを継承して、createGameを実装することで、独自のゲーム製作方法をそれぞれの製作会社が保持することになります。
そのため、プロダクトとなるゲームもサブクラスで拡張するようになります。生成される側のゲームのほうはといいますと、
  1. ゲーム(:プロダクト)スーパークラス(抽象クラス)を用意して
  2. これを継承するゲームサブクラスで、その機能を拡張してデザインされるものです。
これらのデザインを実現するには、上述シンプルファクトリのSimpleFactoryクラス、createGame()メソッドをGameCompanyに持たせることになります。このメソッドは以下のようにGameCompanyの抽象メソッドとし、
    // ファクトリオブジェクトから受け取ったcreateGameメソッド
    abstract Game createGame( String name );
GameCompanyを継承したサブクラスが製作方法を(オーバーライド)実装することで拡張していくのです。

■変更部分の切り出し
シンプルファクトリにも実装されていますが、orderGame()メソッドは、ゲーム製作の過程が実装されています。
  • ゲーム製作の準備(prepare)
  • 製作(produce)
  • 試験(checkProduct)
  • パッケージ(package)
これらは将来変更されることはないでしょう。ゲーム製作というものは、準備をして製作、試験をおこなってからパッケージして販売されるものです。これらのゲーム製作過程そのものがドラスティックにしょっちゅう変更されるということは、ビジネスモデルそのものを抽象化できていないということです。分析からやり直したほうがよいかもしれません。
ちょっと強引な話の進め方ですが、変更や追加・削除されていく箇所は上記のorderGame()ではなく、「どんなゲームをつくるのか?」になります。つまりcreateGame()になります。ファクトリメソッドはこの変更部分を分離してcreateGame()メソッドとしてサブクラスがオーバーライドするという仕組みです。(毎度のことながら、ゲーム会社のゲーム製作工程はよく知りません。話を進める上でのことですので誤りなどありましても気にしないでください。)
// ゲーム製作会社スーパークラス
abstract class GameCompany {
    public Game orderGame( String name ){
        // サブクラスに作成するゲームを決定させる
        Game gameInst = createGame( name );

        gameInst.prepare();
        gameInst.produce();
        gameInst.checkProduct();
        gameInst.package();
        return gameInst;
    }
    
    // ファクトリオブジェクトから受け取ったcreateGameメソッド
    abstract Game createGame( String name );
}
class NiconicoGameCompany extends GameCompany {
    // サブクラスが作成するゲームを決定する
    Game createGame( String name ){
        Game gameInst = null;
        if( name.equals( "やるおの大冒険" ) ){
            gameInst = new ActionGame();
        }
        else if( name.equals( "ニコニコクロニクル" ) ){
            gameInst = new RPGGame();
        }
        // ほかにもたくさん。
        return gameInst;
    }
}

// ゲームクラス。
abstract class Game {
    String category;
    void prepare(){ System.out.println( "設計" ); }
    void produce(){ System.out.println( "製作" ); }
    void checkProduct(){ System.out.println( "テスト" ); }
    void package(){ System.out.println( "パッケージ" );}
}

// ゲームクラスを継承して実装
class ActionGame extends Game {
    public ActionGame(){
        category = "アクション"
    }
    void package(){
        System.out.println( "アクションはパッケージがかっこよくないと!" );
    }
}
     ____       ヽ v / 
   /⌒  ⌒\     -(m)-   
  /( ●)  (●)\       ≡ 
/::::::⌒(__人__)⌒:::::\    
|      `ー'´     | 前々から「変更」するであろう箇所を
/     ∩ノ ⊃  /    抜き出してクラス化・メソッド化してたお。
(  \ / _ノ |  |   今回はnewするインスタンスをいろんな条件に
.\ “  /__|  |    基づいて変えるからここが「変更」箇所だお
  \ /___ / 







   / ̄ ̄\  ( ;;;;( 
 / _ノ  ヽ\ ) ;;;;) 
 |  ( ○) (○)/;;/   
. |   (__人__) l;;,    
  |    ∩ ノ)━・'/   
.  |   /  ノ´ } 条件文がいっぱいあるから
.  ヽ  / /    } 「変更」がかかる箇所ってわけじゃねーだろjk
   ヽ/ /   ノ 







      ____ インスタンスの生成を切り離しておくことで
    /_ノ   ヽ_\たくさんあるゲームの種類の生成が
   /( ●) ( ●)\管理しやすくなったお。
 / ::::::⌒(__人__)⌒:::::\
 |        ̄      |
 \              / 








     ____これ以上おいらが天才になったら
    / ⌒  ⌒  \アーキテクトの立場がなくなるから
  ./( ―) ( ●)  \馬鹿のフリしとくお。
  /::⌒(_人_)⌒:::::  | チラッ
  |    ー       .|
  \          / 







        / ̄ ̄\
      /       \
      |::::::        | とりあえずお前が作りこんだバグは
     . |:::::::::::     | 徹夜してでもなんとかしとけ
       |::::::::::::::    |          ....,:::´, .
     .  |::::::::::::::    }          ....:::,,  ..
     .  ヽ::::::::::::::    }         ,):::::::ノ .
        ヽ::::::::::  ノ        (:::::ソ: .
        /:::::::::::: く         ,ふ´..
-―――――|:::::::::::::::: \ -―,――ノ::ノ――
         |:::::::::::::::|ヽ、二⌒)━~~'´ 







           ____ 
        /⌒  ⌒\ ファクトリわかったから
.      /( ●)  (●)\ 徹夜なんてなんてことないお
     / ::::::⌒(__人__)⌒::::: \ 
    |      |r┬-|     |  
     \       `ー'´     / 
    ノ            \ 
  /´               ヽ                 カ 
 |    l   l||l 从人 l||l      l||l 从人 l||l   カ    タ 
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、.     タ 
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒)) 
     ┌┬┬┐┌┬┬┬┐┌┬┬┬┐┌┬┬┬┐ 
  ,. - ''"| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ρ ̄`l 
   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ノ ̄ 






    |┃三 ガラッ
    |┃  ____
    |┃/⌒  ⌒\
    |┃(●)  (●) \
――‐.|┃:⌒(__人__)⌒:::::\  徹夜すると居室に誰もいなくなって
    |┃  |r┬-|     |⌒)サイコーだお
    |┃   `ー'ォ     //
    (⌒ヽ・    ・ ̄ /
    |┃ノ       /
    |┃   つ   <
    |┃  (::)(::)   ヽ
    |┃/    >  )
    |┃     (__)


    |┃
    |┃  ____
    |┃/⌒  ⌒\
    |┃ (―)  (―)\  フヒー。
――‐.|┃:⌒(__人__)⌒:::::\
    |┃           |
    |┃          /
    |┃ヽ・    ・ ̄ /
    |┃ \    ,.:∴~・:,゜・~・:,゜・ ,
    |┃ヽ_)つ‘∴・゜゜・・∴~・:,゜・・∴
    |┃  (::)(::)  ヽ    ・゜゜・∴~゜
    |┃/    >  )    ゜゜・∴:,゜・~
    |┃     (__)    :,゜・~:,゜・゜゜・~ 











   / ̄ ̄\  やる夫。徹夜ごくろうs
 /   /  \
 |    ( ○)(○)
. |     (__人_(
  |     ` ⌒´(
.  |         }
.  ヽ        }
   ヽ     ノ











    |┃
    |┃  ____
    |┃/⌒  ⌒\
    |┃ (○)  (○)\  お
――‐.|┃:⌒(__人__)⌒:::::\
    |┃           |
    |┃          /
    |┃ヽ・    ・ ̄ /
    |┃ \    ,.:∴~・:,゜・~・:,゜・ ,
    |┃ヽ_)つ‘∴・゜゜・・∴~・:,゜・・∴
    |┃  (::)(::)  ヽ    ・゜゜・∴~゜
    |┃/    >  )    ゜゜・∴:,゜・~
    |┃     (__)    :,゜・~:,゜・゜゜・~ 














        ____
       /      \  ち、違うんです刑事さん・・・。
     /  ─    ─\
    ./    (○)  (○) \
    |       (__人__)    |、
r―n|l\      ` ⌒´   ,/ ヽ
  \\\.` ー‐ ' .// l     ヽ
.     \        |      |
.       \ _  __ | ._   |
        /,  /_ ヽ/、 ヽ_|
\      // /<  __) l -,|__) >
  \.    || | <  __)_ゝJ_)_>
    \.   ||.| <  ___)_(_)_ >
      \_| |  <____ノ_(_)_ ) 
というわけで次回はアブストラクトファクトリでファクトリパターンを締めたいと思います。 ≪第7回第9回≫

★このコンテンツに目的の情報はありませんでしたか?


[ 最近のエントリーとその関連エントリー ]


[ スポンサードリンク ]

トラックバック

このエントリーのトラックバックURL:
http://mojalog.com/cgi/mt/mt-tb.cgi/261

コメントを投稿

ツリータイプ・カテゴリー

open all | close all

リファラから検索


サイト内検索