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

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

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

今回はDecoratorパターンです。

無闇に継承で派生クラスを作成するのではなく派生機能拡張用のDecoratorクラスを作成してより柔軟に対応しようということらしいです。

今回は12. Decorator パターン | TECHSCORE(テックスコア)のアイスクリームの例を真似てみました。

Greg Sullivan氏のGOF Design Patterns in a Dynamic OO Languageによれば、メソッドコンビネーション(around等)で解決できるようなことが書いてありましたが、そっちの方が難しい気がしたので、今回はとりあえず装飾したいクラスをDecoratorクラスのスロットに格納してそれのメソッドを呼び出すことにしました。

(defclass icecream () ())

(defgeneric name (class))
(defgeneric how-sweet (class))

;; 基本タイプ
(defclass vanilla-icecream (icecream) ())

(defmethod name ((self vanilla-icecream))
  "バニラアイスクリーム")

(defmethod how-sweet ((self vanilla-icecream))
  "バニラ味")

(defclass greentea-icecream (icecream) ())

(defmethod name ((self greentea-icecream))
  "抹茶アイスクリーム")

(defmethod how-sweet ((self greentea-icecream))
  "抹茶味")

;; トッピング (Decorator)
(defclass cashew-nuts-topping-icecream (icecream)
  ((icecream :initarg :icecream)))

(defmethod name ((self cashew-nuts-topping-icecream))
  (format nil "カシューナッツ~A" (name (slot-value self 'icecream))))

(defmethod how-sweet ((self cashew-nuts-topping-icecream))
  (how-sweet (slot-value self 'icecream)))

;;; 動作
(let ((x (make-instance 'cashew-nuts-topping-icecream :icecream (make-instance 'vanilla-icecream))))
  (list (name x)
        (how-sweet x)))
;=> ("カシューナッツバニラアイスクリーム" "バニラ味")

(let ((x (make-instance 'cashew-nuts-topping-icecream :icecream (make-instance 'greentea-icecream))))
  (list (name x)
        (how-sweet x)))
;=> ("カシューナッツ抹茶アイスクリーム" "抹茶味")