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-23

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

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

今回はFlyweightパターンです。

Mementoと似た感じで違いが良く分からないのですが、インスタンスの生成に使うのがポイントなんでしょうか。

ということで、普通のフィボナッチ関数に無理矢理メモワイズ機能をつけてみました。

下記のfibクラスはフィボナッチ関数の結果を格納するだけの為に存在していて、要求の分だけインスタンスが作られますが、既に結果を含むインスタンスがあった場合は、それが使い回されます。

fibmeのaroundメソッドがFactoryな感じで考えています。

(defclass memento () 
  ((mementoes :initform (make-hash-table :test #'equal) 
              :accessor mementoes)))

(defclass fib () 
  ((ans :initarg :ans :accessor ans)))

(defgeneric fibme (memento n))
(defmethod fibme ((m memento) n)
  (if (< n 2)
      n
      (+ (fibme m (1- n))
         (fibme m (- n 2)))))

(defmethod fibme :around ((m memento) n)
  (symbol-macrolet ((mem (gethash n (mementoes m))))
    (if mem
        (ans mem)
        (let ((ans (call-next-method)))
          (setf mem (make-instance 'fib :ans ans))
          ans))))

(let ((m (make-instance 'memento)))
  (fibme m 100))
;=> 354224848179261915075