当您使用生产者/消费者关系设计两个类时,如何避免循环依赖?这里ListenerImpl需要对Broadcaster的引用才能注册/取消注册,而Broadcaster需要一个引用回侦听器才能发送消息.此示例使用Java,但它可以应用于任何OO语言.
public interface Listener { void callBack(Object arg); } public class ListenerImpl implements Listener { public ListenerImpl(Broadcaster b) { b.register(this); } public void callBack(Object arg) { ... } public void shutDown() { b.unregister(this); } } public class Broadcaster { private final List listeners = new ArrayList(); public void register(Listener lis) { listeners.add(lis); } public void unregister(Listener lis) {listeners.remove(lis); } public void broadcast(Object arg) { for (Listener lis : listeners) { lis.callBack(arg); } } }
Herms.. 9
我不认为这是一个循环依赖.
听众取决于什么.
ListenerImpl依赖于Listener和Broadcaster
Broadcaster依赖于Listener.
Listener ^ ^ / \ / \ Broadcaster <-- ListenerImpl
所有箭头都在Listener处结束.没有周期.所以,我觉得你没问题.
我不认为这是一个循环依赖.
听众取决于什么.
ListenerImpl依赖于Listener和Broadcaster
Broadcaster依赖于Listener.
Listener ^ ^ / \ / \ Broadcaster <-- ListenerImpl
所有箭头都在Listener处结束.没有周期.所以,我觉得你没问题.
任何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消除了对它们的需求,解决了大多数设计模式问题(例如你的问题).