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

ContextLとデザインパターン - Bridge

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

昨日書いた私が考えるBridgeパターンの例では、機能追加側は一つの定義で良いものの追加された機能のクラスをいちいち継承してやる必要があり、いまいち釈然としなかったのですが、こういう場合は、ContextLが使えるんじゃないかということで、ContextLを使って書いてみました。

  1. 機能の追加は、クラスの継承関係で
  2. 実装の違いはレイヤの違い(継承関係)で

という風にしてみました。もちろん、レイヤとクラスを逆にしても構いません。

これなら、実装と機能追加の双方は独立に追加して行けます。

なんだか、AOPとかリフレクションみたいになってしまいましたが、委譲が良く分かっていない人が書くとBridgeパターンはこうなるのかもしれません。

眺めてみて思うのですが、MOP(ContextL)を使わないということになると、やはりマルチメソッドを使うことになるのかなと思います。

(require :contextl)

(defpackage :design-patterns
  (:use :cl :contextl))

(in-package :design-patterns)

;; time付き用のクラス
(defclass with-time () ())

;; ベース(空実装)
(define-layered-function fib (class n))

;; time付き(ベースを呼んで味付け)
(define-layered-method fib ((class with-time) n)
  (time (call-next-method)))

;; 末尾再帰レイヤ
(deflayer tail)

(define-layered-method fib :in tail (class n)
  (labels ((*fib (n a1 a2)
             (if (< n 2)
                 a1
                 (*fib (1- n) 
                       (+ a1 a2)
                       a1))))
    (*fib n 1 0)))

;; 普通の再帰レイヤ
(deflayer recur)

(define-layered-method fib :in recur (class n)
  (labels ((*fib (n)
             (if (< n 2)
                 n
                 (+ (*fib (1- n))
                    (*fib (- n 2))))))
    (*fib n)))

;;; 動作

;; 普通の再帰
(with-active-layers (recur)
  (let ((n 30))
    (format T "普通:~A~%" (fib 'T n))
    (format T "time付き:~A~%" (fib (make-instance 'with-time) n))))

;;>>>
;; 普通:832040
;; Evaluation took:
;;   0.074 seconds of real time
;;   0.072004 seconds of total run time (0.072004 user, 0.000000 system)
;;   97.30% CPU
;;   178,337,061 processor cycles
;;   114,608 bytes consed
;;  
;; time付き:832040

;; 末尾再帰
(with-active-layers (tail)
  (let ((n 30))
    (format T "普通:~A~%" (fib 'T n))
    (format T "time付き:~A~%" (fib (make-instance 'with-time) n))))
;;>>>
;; 普通:832040
;; Evaluation took:
;;   0.000 seconds of real time
;;   0.000000 seconds of total run time (0.000000 user, 0.000000 system)
;;   100.00% CPU
;;   3,447 processor cycles
;;   0 bytes consed
;;  
;; time付き:832040

ゲスト



トラックバック - http://cadr.g.hatena.ne.jp/g000001/20081212