设计模式两大原则:里式替换原则,将父类替换成子类一定可行;开闭原则:对修改关闭,对扩展开启
monitor也是被观察者Observable和事件发布者publisher。 监视器装在被观察的商店里 如果商品价格有变动,商场去通知消费者和工商局 消费者和工商局 。商场是被观察者是事件消息通知的发布者,工商局和消费者是观察者是事件通知消息的接受者。 观察者(Observer 有的叫监听者 listener在发布订阅模式中又叫订阅者 subcriber)用来接受通知信息。那么观察者接口用定义接受通知的事件函数(行为)。所以观察者类(实现观察者接口)中用来定义事件函数,观察者的具体实现可以定义事件的具体通知行为。这种形式的观察者模式:分两层即观察者和被观察者被观察者
Monitor也叫被观察者Observable 和事件发布者publisher,基本功能可以添加和删除观察者
package com.example.observer;
public interface ProductMonitor {
void addObserver(ProductObserver observer);
void removeObserver(ProductObserver observer);
}
例如spring boot源码ApplicationContext 就是一个被观察者和事件发布者。可以通知注册的监听者:The ability to publish events to registered listeners.
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver
ApplicationContext 通过public void publishEvent(Object event)方法会调用事件多播器根据事件的类型进行广播通知
AbstractApplicationEventMulticaster事件多播器 承担了将事件发布者ApplicationContext (被观察者) 和观察者(订阅者)ApplicationListener结合起来的作用,进行解耦。1.事件多播器可以将相关订阅者进行添加 2.事件多播器可以通知订阅者。从而实现发布和订阅的功能。
1.事件多播器可以将相关订阅者进行添加 如下代码
// AbstractApplicationEventMulticaster
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.retrievalMutex) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
2.事件多播器可以通知订阅者。相关代码如下:
// ApplicationContext执行发布 publishEvent方法最终会执行
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
SimpleApplicationEventMulticaster 简单事件多播器继承了AbstractApplicationEventMulticaster
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
invokeListener最终调的就是listener的onApplicationEvent方法
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
观察者接口/listener/subcriber,定义观察者满足触发条件时的动作(定义事件函数)
package com.example.observer;
public interface ProductObserver {
void onEvent(Product product);
void onPriceChanged(Product product);
}
有些观察者模式把通知变成一个Event对象,从而不再有多种方法通知,而是统一成一种:让观察者自己从Event对象中读取通知类型和通知数据。
public interface ProductObserver {
void onEvent(ProductEvent event);
}
例如spring boot的源码:
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
public abstract class ApplicationEvent extends EventObject {
/** use serialVersionUID from Spring 1.2 for interoperability. */
private static final long serialVersionUID = 7099057708183571937L;
/** System time when the event happened. */
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
/**
* Return the system time in milliseconds when the event happened.
*/
public final long getTimestamp() {
return this.timestamp;
}
}
有些还将观察者Observer和观察者的事件(监听者)listener 进行分离类比c#的委托,比喻的话可以将观察者比作工商局 listener比喻成工商局的工商管理人员,工商管理人员去做具体的动作,监听者和观察者其实是一个单位的,这样一来,观察者Observer中可以添加监听者listener,监听者用来做具体的动作。这种形式的观察者模式分3层:被观察者monitor/Observable ,观察者Observer和监听者listener。向被观察者添加观察者 向观察者添加监听者
如下边源码
FileAlterationMonitor是被观察者
public final class FileAlterationMonitor implements Runnable {
private final List<FileAlterationObserver> observers = new CopyOnWriteArrayList<>();
}
public void addObserver(final FileAlterationObserver observer) {
if (observer != null) {
observers.add(observer);
}
}
public void removeObserver(final FileAlterationObserver observer) {
if (observer != null) {
while (observers.remove(observer)) {
// empty
}
}
}
观察者
public class FileAlterationObserver implements Serializable {
private final List<FileAlterationListener> listeners = new CopyOnWriteArrayList<FileAlterationListener>();
public void addListener(final FileAlterationListener listener) {
if (listener != null) {
listeners.add(listener);
}
}
private void doDelete(FileEntry entry) {
for (FileAlterationListener listener : listeners) {
if (entry.isDirectory()) {
listener.onDirectoryDelete(entry.getFile());
} else {
listener.onFileDelete(entry.getFile());
}
}
}
}
// 监听者
public interface FileAlterationListener {
/**
* File system observer started checking event.
*
* @param observer The file system observer
*/
void onStart(final FileAlterationObserver observer);
/**
* Directory created Event.
*
* @param directory The directory created
*/
void onDirectoryCreate(final File directory);
/**
* Directory changed Event.
*
* @param directory The directory changed
*/
void onDirectoryChange(final File directory);
/**
* Directory deleted Event.
*
* @param directory The directory deleted
*/
void onDirectoryDelete(final File directory);
/**
* File created Event.
*
* @param file The file created
*/
void onFileCreate(final File file);
/**
* File changed Event.
*
* @param file The file changed
*/
void onFileChange(final File file);
/**
* File deleted Event.
*
* @param file The file deleted
*/
void onFileDelete(final File file);
/**
* File system observer finished checking event.
*
* @param observer The file system observer
*/
void onStop(final FileAlterationObserver observer);
}
类似这种结构
定义一个产品
package com.example.observer;
public class Product {
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return String.format("{Product: name=%s, price=%s}", name, price);
}
}
自己写的简单的小程序作为实例:
被观察者Store 添加观察者,发布事件通知
package com.example.observer;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Store implements ProductMonitor{
private List<ProductObserver> observers = new CopyOnWriteArrayList<>();
private Map<String, Product> products = new ConcurrentHashMap<>();
ExecutorService threadPool=Executors.newFixedThreadPool(5);
// 添加观察者
public void addObserver(ProductObserver observer) {
this.observers.add(observer);
}
public void removeObserver(ProductObserver observer) {
this.observers.remove(observer);
}
public void addNewProduct(String name, double price) {
Product p = new Product(name, price);
products.put(p.getName(), p);
// 发布消息 通知
// observers.forEach(o -> o.onEvent(p));
observers.forEach(o->{
threadPool.execute(()->{
o.onEvent(p);
});
});
}
public void setProductPrice(String name, double price) {
Product p = products.get(name);
p.setPrice(price);
// observers.forEach(o -> o.onEvent(p));
// 发布消息 通知
observers.forEach(o->{
threadPool.execute(()->{
o.onPriceChanged(p);
});
});
}
}
在客户端订阅(注册),观察者 Customer Admin 和匿名观察者
package com.example.observer;
public class Host {
public static void main(String[] args) {
// observer:
Admin a = new Admin();
Customer c = new Customer();
// store:
Store store = new Store();
// register:
store.addObserver(a);
store.addObserver(c);
// 注册匿名观察者:
store.addObserver(new ProductObserver() {
@Override
public void onEvent(Product product) {
System.out.println("[Log] on product published: " + product);
}
@Override
public void onPriceChanged(Product product) {
System.out.println("[Log] on product price changed: " + product);
}
});
// operation:
store.addNewProduct("Design Patterns", 35.6);
store.addNewProduct("Effective Java", 50.8);
store.setProductPrice("Design Patterns", 31.9);
}
}
class Customer implements ProductObserver {
@Override
public void onEvent(Product product) {
System.out.println("[Customer] on product published: " + product);
}
@Override
public void onPriceChanged(Product product) {
System.out.println("[Customer] on product price changed: " + product);
}
}
class Admin implements ProductObserver {
@Override
public void onEvent(Product product) {
System.out.println("[Admin] on product published: " + product);
}
@Override
public void onPriceChanged(Product product) {
System.out.println("[Admin] on product price changed: " + product);
}
}
结果
[Customer] on product published: {Product: name=Design Patterns, price=35.6}
[Customer] on product published: {Product: name=Effective Java, price=50.8}
[Admin] on product published: {Product: name=Design Patterns, price=35.6}
[Admin] on product published: {Product: name=Effective Java, price=50.8}
[Log] on product published: {Product: name=Design Patterns, price=35.6}
[Admin] on product price changed: {Product: name=Design Patterns, price=31.9}
[Log] on product published: {Product: name=Effective Java, price=50.8}
[Log] on product price changed: {Product: name=Design Patterns, price=31.9}
[Customer] on product price changed: {Product: name=Design Patterns, price=31.9}
应用:监听文件变化
maven依赖
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
自定义监听者的事件
package com.example.observerExample;
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import java.io.File;
/**
* 事件监听者:自定义监听者的事件
*/
public class MyFileListenerAdaptor extends FileAlterationListenerAdaptor {
@Override
public void onFileChange(File file) {
System.out.println("change.............");
}
@Override
public void onStart(FileAlterationObserver observer) {
System.out.println("start");
}
@Override
public void onStop(FileAlterationObserver observer) {
System.out.println("stop");
}
@Override
public void onDirectoryChange(File directory) {
System.out.println("dir change.........");
}
@Override
public void onDirectoryCreate(File directory) {
System.out.println("dir create.........");
}
@Override
public void onDirectoryDelete(File directory) {
System.out.println("dir delete.........");
}
}
为监视器添加观察者,并为观察者添加事件监听者
package com.example.observerExample;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
public class MyFileAlterationMonitor {
private String path; // 文件夹目录
private String fileSuffix; // 需要监听的文件名后缀
private long interval; // 监听间隔
private static final long DEFAULT_INTERVAL = 10 * 1000; // 默认监听间隔10s
private FileAlterationListenerAdaptor listener; // 事件处理类对象
public MyFileAlterationMonitor(){
this.interval = DEFAULT_INTERVAL;
}
public MyFileAlterationMonitor(String path, String fileSuffix, FileAlterationListenerAdaptor listenerAdaptor){
this.path = path;
this.fileSuffix = fileSuffix;
this.interval = DEFAULT_INTERVAL;
this.listener = listenerAdaptor;
}
public MyFileAlterationMonitor(String path, String fileSuffix, long interval, FileAlterationListenerAdaptor listenerAdaptor) {
this.path = path;
this.fileSuffix = fileSuffix;
this.interval = interval;
this.listener = listenerAdaptor;
}
/***
* 开启监听
*/
public void start() {
if(path==null) {
throw new IllegalStateException("Listen path must not be null");
}
if(listener==null) {
throw new IllegalStateException("Listener must not be null");
}
// FileAlterationMonitor本身实现了 Runnable
FileAlterationMonitor monitor = new FileAlterationMonitor(interval);
// 设定观察者,监听.properties文件
FileAlterationObserver observer = new FileAlterationObserver(path,
FileFilterUtils.suffixFileFilter(fileSuffix));
monitor.addObserver(observer);
// 给观察者添加监听事件
observer.addListener(listener);
try {
monitor.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void setPath(String path) {
this.path = path;
}
public void setFileSuffix(String fileSuffix) {
this.fileSuffix = fileSuffix;
}
public void setAdaptor(FileAlterationListenerAdaptor listenerAdaptor) {
this.listener = listenerAdaptor;
}
}
Main方法
package com.example.observerExample;
public class Test {
public static void main(String[] args) {
String path=Test.class.getClassLoader().getResource("").getPath();
System.out.println(path);
MyFileAlterationMonitor monitor = new MyFileAlterationMonitor(
path,
"",
new MyFileListenerAdaptor());
monitor.start();
}
}
结果:文件改变时结果变化如下
stop
start
stop
start
change…
stop