文件路徑監控項目中觀察者模式的分析
阿新 • • 發佈:2018-10-26
實現 throws over don ogg align 自己的 穩定 ack
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、效果
- 可以實現表示層和數據邏輯層的分離,並定義了穩定的消息更新傳遞機制,抽象了更新接口,使得可以有各種各樣不同的表示層作為具體觀察者角色。
- 在觀察目標和觀察者之間建立一個抽象的耦合。
- 支持廣播通信。
- 符合“開閉原則”的要求。
文件路徑監控項目中觀察者模式的分析