スポンサーサイト

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

F#によるデザインパターン入門 Command パターン(1)

Commandパターンは、動作用のコードをオブジェクトとして取り扱うというパターンです。
構造としては共通のインターフェイス(下の例ではメソッドExecuteを実装)を共有する多数のクラスから構成されます。
 

 
> //インターフェイス
type Icommand =
  abstract Execute : unit -> unit  
 
//クラスの定義
type ShowNum (i:int) =
    interface Icommand with
        member this.Execute () =
            printfn "%d" i
 
type ShowTwoNum (i:int,j:int) =
    interface Icommand with
        member this.Execute () =
            printfn "%d %d" i j
 
type ShowStr (st :string) =
    interface Icommand with
        member this.Execute () =
            printfn "%s" st;;
 
type Icommand =
  interface
    abstract member Execute : unit -> unit
  end
type ShowNum =
  class
    interface Icommand
    new : i:int -> ShowNum
  end
type ShowTwoNum =
  class
    interface Icommand
    new : i:int * j:int -> ShowTwoNum
  end
type ShowStr =
  class
    interface Icommand
    new : st:string -> ShowStr
  end
 
Icommand型にキャストする補助関数toIcを定義しておきます。
 
> let toIc (x:obj) = 
        x :?> Icommand;;
 
val toIc : obj -> Icommand
 
Icommand型のインスタンスをいくつか生成してみます。
 
> //インスタンスの生成
let sn1 = new ShowNum (3) |> toIc
let sn2 = new ShowNum (7) |> toIc
let stn1 = new ShowTwoNum (1,2) |> toIc
let ss1 = new ShowStr ("one") |> toIc
let ss2 = new ShowStr ("two") |> toIc;;
 
val sn1 : Icommand
val sn2 : Icommand
val stn1 : Icommand
val ss1 : Icommand
val ss2 : Icommand
 
こうしておけば、Icommand型のオブジェクトは配列等に保存可能なので、実行の履歴を保存したりする用途に使用可能です。例えばWindowsアプリケーションで複数のボタンを配置し、それぞれのボタンにIcommand型のオブジェクトを対応させておき、ボタンが押されたときに、そのオブジェクトのExecuteメソッドを実行し、同時にリスト等に保存しておけば、実行の履歴を残すことができます。
 
例えば、あるプログラムで、履歴が
 
> let his00= [stn1;ss1;ss2;sn1];;
 
val his00 : Icommand list =
  [FSI_0002+ShowTwoNum; FSI_0002+ShowStr; FSI_0002+ShowStr; FSI_0002+ShowNum]
  
というようにリストに保存されているのであれば、同じ動作を次のように再現できます。
 
> List.iter (fun (com:Icommand) -> com.Execute ()) his00;;
1 2
one
two
3
val it : unit = ()
 
さて、上の例では履歴全体も実行できる、ひと塊のコードでしたので、これもクラス化して、Icommandインターフェイスを備えさせてみます。(いわゆるCompositパターンです。)
> type CompShow () =
    let mutable (cmds : list<Icommand>) = []
 
    interface Icommand with
        member this.Execute () =
            List.iter (fun (com:Icommand) -> com.Execute ()) cmds
 
    member this.Add (com:Icommand) =
        cmds <- com :: cmds;;
 
type CompShow =
  class
    interface Icommand
    new : unit -> CompShow
    member Add : com:Icommand -> unit
  end
 
使用してみます。
 
> let sc1 = new CompShow()
sc1.Add(sn1)
sc1.Add(stn1)
(sc1:>Icommand).Execute();;
1 2
3
 
val sc1 : CompShow
 
これでsc1自身もIcommandインターフェイスを備えるオブジェクトですので、さらに入れ子にもできます。
 
> let sc2 = new CompShow()
sc2.Add(sc1)
sc2.Add(sn1)
(sc2:>Icommand).Execute();;
3
1 2
3
 
val sc2 : CompShow
スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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