1、概述
观察者模式是软件设计模式的一种,它描述了如何建立对象与对象之间的依赖关系,如何构造满足这种需求的系统。这一模式中的关键对象是观察目标和观察者,一个目标可以有任意数目的与之相依赖的观察者,一旦目标的状态发生改变,所有的观察者都将得到通知。作为对这个通知的响应,每个观察者都将即时更新自己的状态,以与目标状态同步,这种交互也称为发布-订阅(publish-subscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅它并接收通知。
该模式包含四种角色:
- 抽象被观察者角色:也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
- 抽象观察者角色:为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
- 具体被观察者角色:也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。
- 具体观察者角色:实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。
观察者模式结构图
2、实现
抽象观察者:
package directoryobserver; import org.apache.commons.io.*; import org.apache.commons.io.filefilter.*; import org.apache.commons.io.monitor.*; import org.apache.log4j.*; import java.io.*; public class DirectoryObserver { private final IOFileFilter doneFileFilter; private FileAlterationObserver observer; private Logger log = Logger.getLogger(DirectoryObserver.class); private File directory; static boolean isStarting = false; public DirectoryObserver(File directory) { this.directory = directory; doneFileFilter = FileFilterUtils.suffixFileFilter(".done"); observer = new FileAlterationObserver(directory, doneFileFilter); } public void addListener(NewFileListener listener) { observer.addListener(new DoneFileAlterationListener(listener)); } public void start() throws Exception { FileAlterationMonitor monitor = new FileAlterationMonitor(500, observer); isStarting = true; monitor.start(); log.info("Watching for new files..."); for (FileAlterationListener listener : observer.getListeners()) { for (File doneFile : FileUtils.listFiles(directory, doneFileFilter, FileFilterUtils.directoryFileFilter())) { listener.onFileCreate(doneFile); } } isStarting = false; } }
具体观察者:
package directoryobserver; import org.apache.commons.codec.digest.*; import org.apache.commons.io.monitor.*; import org.apache.log4j.*; import java.io.*; final class DoneFileAlterationListener implements FileAlterationListener { private final NewFileListener newFileListener; private Logger log = Logger.getLogger(DoneFileAlterationListener.class); public DoneFileAlterationListener(NewFileListener newFileListener) { this.newFileListener = newFileListener; } @Override public void onStop(FileAlterationObserver observer) { } @Override public void onStart(FileAlterationObserver observer) { } @Override public void onFileDelete(File file) { } @Override public void onFileCreate(File doneFile) { try { log.info("Received done file " + doneFile.getName()); if(doneFile.exists()) { String[] tokens = doneFile.getName().split("\\."); if (tokens.length != 3) { newFileListener.onError(doneFile, new WrongDoneFileName()); return; } String name = tokens[0]; String md5 = tokens[1]; File newFile = new File(doneFile.getParent() + File.separator + name); String calculatedMd5 = DigestUtils.md5Hex(new FileInputStream(newFile)); if (calculatedMd5.equals(md5)) { newFileListener.onNewFile(newFile); } else { newFileListener.onChecksumMismatch(newFile, doneFile); } } else if(!DirectoryObserver.isStarting) { newFileListener.onError(doneFile, new DoneFileException()); } } catch (Exception e) { newFileListener.onError(doneFile, e); } finally { doneFile.delete(); } } @Override public void onFileChange(File file) { } @Override public void onDirectoryDelete(File directory) { } @Override public void onDirectoryCreate(File directory) { } @Override public void onDirectoryChange(File directory) { } }
观察者观察路径中的文件,当文件发生改变时,观察者可以得到通知,并进行相应的操作。
3、效果
- 可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
- 在观察目标和观察者之间建立一个抽象的耦合。
- 支持广播通信。
- 符合“开闭原则”的要求。
原文地址:https://www.cnblogs.com/haoyj/p/9853150.html
时间: 2024-10-29 19:07:53