观察者模式(Observer)
观察者模式是一种行为型设计模式。
可以用来定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。
优点:
缺点:
后面讲到再写。
观察者模式有不同的代码实现方式: 有同步阻塞/异步非阻塞的实现方式; 有进程内/跨进程的实现方式。
接口定义:
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String msg);
}
public interface Observer {
void update(String msg);
}
RSS 服务端 (被观察者主体)
public class RssSubject implements Subject{
private List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers(String msg) {
// 通知每一个订阅者
for (Observer observer : observers) {
observer.update(msg);
}
}
}
RSS 订阅对象(观察者)
public class RssObserver implements Observer {
// 当前订阅者用户名
private String user;
// 记录最后信息,方便测试用
private String lastMessage;
// 记录消息总数,方便测试用
private int count;
public RssObserver(String user) {
this.user = user;
}
// 收到推送的执行方法
@Override
public void update(String msg) {
System.out.println("当前用户[" + user + "]收到推送信息:" + msg);
lastMessage = msg;
count++;
}
// 方便测试用
public String getLastMessage() {
return lastMessage;
}
public int getCount() {
return count;
}
}
测试代码
public class ObserverTest {
@Test
public void test() {
// RSS 服务端 (被观察者主体)
RssSubject rssSubject = new RssSubject();
// rss 订阅对象(观察者)
RssObserver observer1 = new RssObserver("用户A");
RssObserver observer2 = new RssObserver("用户B");
RssObserver observer3 = new RssObserver("用户C");
RssObserver observer4 = new RssObserver("用户D");
// 把观察者注册到主体(相当于订阅了通知,有新推送则会收到)
rssSubject.registerObserver(observer1);
rssSubject.registerObserver(observer2);
rssSubject.registerObserver(observer3);
// 推送信息
rssSubject.notifyObservers("早上推送文章《论观察者模式1》");
Assertions.assertEquals(1,observer1.getCount());
Assertions.assertEquals(0,observer4.getCount());
rssSubject.removeObserver(observer3);
rssSubject.registerObserver(observer4);
rssSubject.notifyObservers("晚上推送文章《论观察者模式2》");
Assertions.assertEquals(2,observer1.getCount());
Assertions.assertEquals(1,observer3.getCount());
Assertions.assertEquals(1,observer4.getCount());
Assertions.assertEquals("早上推送文章《论观察者模式1》",observer3.getLastMessage());
}
}
java.util.Observer、Observable (已过时)
java.util.EventListener(广泛存在于 Swing 组件中)
EventBus:同步阻塞的观察者模式
public class EventBus {
private final String identifier;
private final Executor executor;
private final SubscriberExceptionHandler exceptionHandler;
private final SubscriberRegistry subscribers = new SubscriberRegistry(this);
private final Dispatcher dispatcher;
// ... 省略
EventBus(
String identifier,
Executor executor,
Dispatcher dispatcher,
SubscriberExceptionHandler exceptionHandler) {
this.identifier = checkNotNull(identifier);
this.executor = checkNotNull(executor);
this.dispatcher = checkNotNull(dispatcher);
this.exceptionHandler = checkNotNull(exceptionHandler);
}
public void register(Object object) {
subscribers.register(object);
}
public void unregister(Object object) {
subscribers.unregister(object);
}
// 利用 @Subscribe 注解可以实现 发送给匹配类型的观察者,而不是发送全部
public void post(Object event) {
Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
if (eventSubscribers.hasNext()) {
dispatcher.dispatch(event, eventSubscribers);
} else if (!(event instanceof DeadEvent)) {
// the event had no subscribers and was not itself a DeadEvent
post(new DeadEvent(this, event));
}
}
// ... 省略
}
AsyncEventBus:异步非阻塞的观察者模式
public class AsyncEventBus extends EventBus {
public AsyncEventBus(String identifier, Executor executor) {
super(identifier, executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
}
public AsyncEventBus(Executor executor, SubscriberExceptionHandler subscriberExceptionHandler) {
super("default", executor, Dispatcher.legacyAsync(), subscriberExceptionHandler);
}
public AsyncEventBus(Executor executor) {
super("default", executor, Dispatcher.legacyAsync(), LoggingHandler.INSTANCE);
}
}
以上代码与文章会同步到 github 仓库:
/chenbihao/Design-Patterns