這是本文件的舊版!


Observer使用Lambda寫法進行通知的例外處理 (Working)

這是一段常見的Observer寫法的程式碼,FileWatcher是Subject負責確認檔案是否修改,而IFileChangedListener是Observer接收檔案改變通知;當檔案改變時,FileWatcher會執行doOnChange通知各個IFileChangedListener:

public class FileWatcher extends FileWatchdog {

	private List<IFileChangedListener> listeners = new ArrayList<>();
	static private Logger logger = LoggerFactory.getLogger(FileWatcher.class);

	public FileWatcher(String filename) {
		super(filename);
	}

	@Override
	protected void doOnChange() {
		try {
			if( listeners == null || listeners.isEmpty() )
				return;
			
			String newContent = new String(Files.readAllBytes(Paths.get(super.filename)));
			listeners.forEach(listener->listener.update(newContent));
		} catch( IOException e ){
			throw new RuntimeException(e);
		}
	}
	
	public void addListener(IFileChangedListener listener){
		listeners.add(listener);
	}
}
假設我有10個listener,當第三個listener執行update時發生了例外,工作是不是就會停止了呢? 答案是肯定的。本篇主要分享可能的例外處理方式。

最直接的方法就是把例外處理弄成一個區塊:

listeners.forEach(listener->{
	try {
		listener.update(newContent);
	} catch( Exception e ) {
		logger.warn("Update file info failed.", e);
	}
});
但隨著不同例外處理需求或流程,會變得難以閱讀而喪失原本Lambda的美意。

以Lambda方式實作時,將處理抽成method以增加可讀性是常使用的做法:

listeners.forEach(listener->updateEx(listener, newContent));
 
private void updateEx(IFileChangedListener listener, String newContent){
	try {
		listener.update(newContent);
	} catch( Exception e ) {
		logger.warn("Update file info failed.", e);
	}
}
接下來就是考慮重複使用的議題。