观察者模式
当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化,对象之间是一种一对多的关系!
UML
Java
- 定义观察者接口Observer,当被观察的对象发生变化时,会调用这个接口的update方法:
public interface Observer { void update(); }
- 实现2个具体的观察者类:
public class Observer1 implements Observer { @Override public void update() { System.out.println("observer1 has received!"); } }
public class Observer1 implements Observer { @Override public void update() { System.out.println("observer1 has received!"); } }
- 定义被观察者的接口Subject:
public interface Subject { /*增加观察者*/ public void add(Observer observer); /*删除观察者*/ public void del(Observer observer); /*通知所有的观察者*/ public void notifyObservers(); /*自身的操作*/ public void operation(); }
- 实现对观察者Observer的基本操作:
public abstract class AbstractSubject implements Subject { private Vector<Observer> observers = new Vector<>(); @Override public void add(Observer observer) { observers.add(observer); } @Override public void del(Observer observer) { observers.remove(observer); } @Override public void notifyObservers() { for (Observer observer : observers) observer.update(); } }
- 实现被观察者真正的业务逻辑:
public class MySubject extends AbstractSubject { @Override public void operation() { System.out.println("update self!"); notifyObservers(); } }
- 测试类:
public class ObserverTest { public static void main(String[] args) { Subject sub = new MySubject(); sub.add(new Observer1()); sub.add(new Observer2()); sub.operation(); } }
- 测试结果:
update self! observer1 has received! observer2 has received!
CLOS
- 定义观察者的通用方法:
(defclass observer () ()) (defclass observer1 (observer) ()) (defclass observer2 (observer) ()) (defmethod update ((o observer1)) (format t "observer1 has received! ~C" #\linefeed)) (defmethod update ((o observer2)) (format t "observer2 has received! ~C" #\linefeed))
- 使用辅助方法:after实现更新:
(defclass subject () ((observers :accessor subject-observers :initarg :observers :initform '()))) (defmethod operation ((s subject)) (format t "update self! ~C" #\linefeed)) ;;依次调用观察者列表中每个元素的update方法 (defmethod operation :after ((s subject)) (mapc #'update (subject-observers s)))
- 测试:
(setf s (make-instance 'subject :observers (list (make-instance 'observer1) (make-instance 'observer2)))) (operation s) ;; => update self! ;; observer1 has received! ;; observer2 has received!