スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#によるデザインパターン入門 テンプレートパターン(1)

今回はテンプレートパターンです。
 
まず二つの作業A,Bがあるとします。
どちらの作業もいくつかの手順に分かれているけれども、手順の構成は同じだとします。
たとえば、何かを書き出す場合、書き出す対象が何であれ、普通はopen->write->closeの手順に従います。
手紙を書くにしろ、前置き->本文->結びという手順で行われます。この決まり切った流れをテンプレート処理というようにいいます。(いわゆる雛型です。)
この決まり切った流れを親クラス側で表記しておいて、ケース別にクラスを派生させてそちらの派生したクラス側で其々のケースの個々の処理を実装していくというのが、いわゆるテンプレートパターンというものです。
 
まずここではレポートを作ることを考えます。決まり切った流れとして、トップ部分を作る。内容部分を作る。エンド部分を作る。という3つの工程に分けます。与える材料は、タイトルと内容とします。
それでは、決まり切った流れを記述する(工程を分ける部分と、工程を統合する部分があります)親クラスをAbstractMakeReportクラスとして次のように定義します。
 
[<AbstractClass>]
type AbstractMakeReport (title :string,contentsLst :list<string>)    =
    //この下3つが工程を分ける部分
    abstract member makeTop : string -> string
    abstract member makeMiddle : list<string> -> string
    abstract member makeBottom : unit -> string
    //次のが工程を統合する部分
    member this.makeUpReport () =
        (this.makeTop title) + (this.makeMiddle contentsLst) + (this.makeEnd ()) //文字の連結
 
3つのメソッドmakeTop,makeMiddle,makeBottomが細かい工程で、makeUpReportがその工程の組み合わせ方を決めるメソッドです。
 
それでは、まずは普通のレポートを返すクラスを派生させてみます。
 
type PlainReportMaker (title :string,contentsLst :list<string>)    =
    inherit AbstractMakeReport(title,contentsLst)
    override this.makeTop() =
         title+"\n"
    override this.makeMiddle() =
        List.fold (fun s ele -> s + ele + "\n") "" contentsLst
    override this.makeBottom() = "以上"
    
使ってみます。
 
> let testPlain = new PlainReportMaker ("今日の料理",["卵焼き";"鮭";"漬物"]);;
val testPlain : PlainReportMaker
 
> printfn "%s" (testPlain.makeUpReport());;
今日の料理
卵焼き

漬物
以上
val it : unit = ()
 
次に少し装飾を加えたレポートを返すクラスを派生させてみます。
 
type DecoratedReportMaker (title :string,contentsLst :list<string>)    =
    inherit AbstractMakeReport(title,contentsLst)
    override this.makeTop() =
        "--------- " + title + " -----------\n"
    override this.makeMiddle() =
        List.fold (fun s ele -> s + "○" + ele + "\n") "" contentsLst
    override this.makeBottom() = "-----------以上-----------------"
 
使ってみます。
> let testDeco  = new DecoratedReportMaker ("今日の料理",["卵焼き";"鮭";"漬物"]);;
val testDeco : DecoratedReportMaker
 
> printfn "%s" (testDeco.makeUpReport());;
--------- 今日の料理 -----------
○卵焼き
○鮭
○漬物
-----------以上-----------------
val it : unit = ()
 
このようにしていけば,例えばhtml文書の形のレポートを返すクラスも同様に定義できます。
 
上の例は3つの工程を順に施すという単純なものなので、「こんなの一つの工程にしてしまえばいいのでは」というような疑問点もでると思いますが、複雑な工程とか、同じ工程を繰り返し使う場合とかは、分けておいた方が、頭の整理もしやすいと思いますし、エラーも出にくいのではないかと思います。また、例えば3つの工程の内2つは共通だけども、一つだけ異なるという場合などは、2つの共通工程だけ実装したクラスを派生して、更に残りの一工程だけの実装が違うクラスをさらに派生させることもできます。
 
まとめると、テンプレートパターンというのは、派生元クラスで工程の分け方と、その組み合わせ方を定め、派生先クラスで、各工程の具体的内容を定めるようなパターンです。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。