任何OOP語言?好。這是CLOS的十分鐘版本。
廣播框架
(defclass broadcaster()
((listeners :accessor listeners
:initform '())))
(defgeneric add-listener (broadcaster listener)
(:documentation "Add a listener (a function taking one argument)
to a broadcast's list of interested parties"))
(defgeneric remove-listener (broadcaster listener)
(:documentation "Reverse of add-listener"))
(defgeneric broadcast (broadcaster object)
(:documentation "Broadcast an object to all registered listeners"))
(defmethod add-listener (broadcaster listener)
(pushnew listener (listeners broadcaster)))
(defmethod remove-listener (broadcaster listener)
(let ((listeners (listeners broadcaster)))
(setf listeners (remove listener listeners))))
(defmethod broadcast (broadcaster object)
(dolist (listener (listeners broadcaster))
(funcall listener object)))
實施例的子類
(defclass direct-broadcaster (broadcaster)
((latest-broadcast :accessor latest-broadcast)
(latest-broadcast-p :initform nil))
(:documentation "I broadcast the latest broadcasted object when a new listener is added"))
(defmethod add-listener :after ((broadcaster direct-broadcaster) listener)
(when (slot-value broadcaster 'latest-broadcast-p)
(funcall listener (latest-broadcast broadcaster))))
(defmethod broadcast :after ((broadcaster direct-broadcaster) object)
(setf (slot-value broadcaster 'latest-broadcast-p) t)
(setf (latest-broadcast broadcaster) object))
實施例代碼
Lisp> (let ((broadcaster (make-instance 'broadcaster)))
(add-listener broadcaster
#'(lambda (obj) (format t "I got myself a ~A object!~%" obj)))
(add-listener broadcaster
#'(lambda (obj) (format t "I has object: ~A~%" obj)))
(broadcast broadcaster 'cheezburger))
I has object: CHEEZBURGER
I got myself a CHEEZBURGER object!
Lisp> (defparameter *direct-broadcaster* (make-instance 'direct-broadcaster))
(add-listener *direct-broadcaster*
#'(lambda (obj) (format t "I got myself a ~A object!~%" obj)))
(broadcast *direct-broadcaster* 'kitty)
I got myself a KITTY object!
Lisp> (add-listener *direct-broadcaster*
#'(lambda (obj) (format t "I has object: ~A~%" obj)))
I has object: KITTY
不幸的是,Lisp中通過消除需要解決了大多數的設計圖案的問題(如你的)爲他們。
但還是有參考週期 - 播音員具有參考到具體的ListenerImpl對象,即使引用的類型是Listener接口類型。參考循環是否意味着依賴循環? – 2008-09-29 16:55:31
沒有真正的方法去除參考週期。這是這種類型的東西需要的。鑑於任何好的垃圾收集器都可以處理它們,所以引用週期現在不是真正的問題。它是你需要擔心的依賴循環。 – Herms 2008-09-29 17:05:56