Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2008-12-20

CLとデザインパターン - Mediator

| 18:32 | CLとデザインパターン - Mediator - わだばLisperになる を含むブックマーク はてなブックマーク - CLとデザインパターン - Mediator - わだばLisperになる

今回はMediatorパターンです。

中央管制塔のように全体を統轄するMediatorを作成して部品(Colleague)間を管理することにより協調をとるパターンのようです。

Norvig氏のDesign Patterns in Dynamic Programmingでは、メソッドコンビネーションで実現できるようなことが書いてありました。Observerだと通知を:afterメソッドで実現してみましたが、確かに通知には使えるかもしれません。

毎回大体概念は分かるのですが、具体的に動く例を考えるのが難儀です。デザインパターンのドリルとかあると良いのですが…。

コードの解説ですが、colleagueクラスを継承したc1〜3を作成し、それぞれのメソッドは、0-9、0-5、0-3の範囲でそれぞれ乱数を返します。

Mediatorは、 Colleague のリストを持っており、各々の colleagueの返す乱数の結果が10を越えなければ、もう一度実行します。

なんとも無理矢理ですが、双方向通信ということでこんな風にしてみました。

(defclass colleague () ())
(defclass c1 (colleague) ())
(defclass c2 (colleague) ())
(defclass c3 (colleague) ())

(defclass mediator () 
  ((colleagues :initform () :initarg :colleagues :accessor colleagues)))

(defgeneric rand (class))
(defmethod rand ((c c1))
  (random 10))
(defmethod rand ((c c2))
  (random 5))
(defmethod rand ((c c3))
  (random 3))

(defgeneric mediator (class))
(defmethod mediator ((class mediator))
  (mapcar (lambda (c)
            ;; 合計が10を越えるまで繰り返し
            (loop :for x := (rand c) 
                  :until (> sum 10) 
                  :sum x :into sum
                  :collect x))
          (colleagues class)))


(rand (make-instance 'c3))
(let ((m (make-instance 'mediator 
                        :colleagues (list (make-instance 'c1)
                                          (make-instance 'c2)
                                          (make-instance 'c3)))))
  (mediator m))
;=> ((9 9) (2 2 3 3 1) (2 2 0 1 2 2 2))