FileObserver-android项目——观察者模式应用分析

项目的GitHub来源:https://github.com/doyee/FileObserver-android/blob/master/FileObserver/src/custom/fileobserver/FileObserver.java

https://github.com/doyee/FileObserver-android/blob/master/FileObserver/src/custom/fileobserver/FileWatcher.java

1、概述

      观察者模式是一种对象的行为模式,也叫做发布-订阅模式、源-监听器模式或从属者模式。观察者模式可以让多个观察者同时监听某一个主题对象,从而形成一对多的依赖关系,当主题对象状态发生变化的时候,就会通知所有观察者对象,使它们能够自动更新。理想的观察者模式使用还应避免或者降低对象之间的耦合。

       1)抽象主题:抽象主题负责将所有的观察者对象引用保存到一个聚集里,每个主题都可以有相当数量的观察者。在抽象主题中会提供一个接口,来增加和删除观察者对象。

       2)具体主题:具体主题就是用来把相关的状态存入具体观察者对象,在具体主题内部状态改变时,给所有登记过的观察者发出通知。

       3)抽象观察者:抽象观察者负责给所有的具体观察者定义一个接口,在得到主题通知时更新自己。

      4)具体观察者:具体的观察者就是实现抽象观察者角色所要求的更新接口,以此来使自己的状态和主题状态相一致。

2、观察者主题抽象对象:

public abstract class FileObserver {
 /** Event type: Data was read from a file */
    public static final int ACCESS = 0x00000001;
    /** Event type: Data was written to a file */
    public static final int MODIFY = 0x00000002;
    /** Event type: Metadata (permissions, owner, timestamp) was changed explicitly */
    public static final int ATTRIB = 0x00000004;
    /** Event type: Someone had a file or directory open for writing, and closed it */
    public static final int CLOSE_WRITE = 0x00000008;
    /** Event type: Someone had a file or directory open read-only, and closed it */
    public static final int CLOSE_NOWRITE = 0x00000010;
    /** Event type: A file or directory was opened */
    public static final int OPEN = 0x00000020;
    /** Event type: A file or subdirectory was moved from the monitored directory */
    public static final int MOVED_FROM = 0x00000040;
    /** Event type: A file or subdirectory was moved to the monitored directory */
    public static final int MOVED_TO = 0x00000080;
    /** Event type: A new file or subdirectory was created under the monitored directory */
    public static final int CREATE = 0x00000100;
    /** Event type: A file was deleted from the monitored directory */
    public static final int DELETE = 0x00000200;
    /** Event type: The monitored file or directory was deleted; monitoring effectively stops */
    public static final int DELETE_SELF = 0x00000400;
    /** Event type: The monitored file or directory was moved; monitoring continues */
    public static final int MOVE_SELF = 0x00000800;
 public static final int UNMOUNT = 0x00002000;
    public static final int Q_OVERFLOW = 0x00004000;
    public static final int IGNORED = 0x00008000; 
    public static final int CLOSE = (CLOSE_WRITE | CLOSE_NOWRITE);
    public static final int MOVE  = (MOVED_FROM | MOVED_TO);

    public static final int ONLYDIR = 0x01000000;
    public static final int DONT_FOLLOW = 0x02000000;
    public static final int MASK_ADD = 0x20000000; 
    public static final int ISDIR   = 0x40000000 ;
    public static final int ONESHOT = 0x80000000; 
  /** Event mask: All valid event types, combined */
    public static final int ALL_EVENTS = ACCESS | MODIFY | ATTRIB | CLOSE_WRITE
            | CLOSE_NOWRITE | OPEN | MOVED_FROM | MOVED_TO | DELETE | CREATE
            | DELETE_SELF | MOVE_SELF;
    public static int FILE_CHANGED = CREATE | DELETE | MOVED_FROM | MOVED_TO | CLOSE_WRITE;/* MODIFY | ATTRIB*/;
    private static final String LOG_TAG = "FileObserver";
   private static class FolderFilter implements FileFilter{...  }
 private static class ObserverThread extends Thread {...}
......
}

  这个FileObserver是一个抽象类,这里简略打出,详细代码见GitHub链接源代码,这个FileObserver类中首先定义了一系列常量数据结构,用来区分各种不同的文件及目录的事件状态,例如有:1)数据在一个文件中已被打开状态;

               2)数据在一个文件中被写入状态;

               3)  元数据被修改;

               4)  某人对一个文件或目录有打开写入并关闭的权限;

               5)  某人对一个目录或文件只读权限;

               6)  一个文件或目录已经被打开状态;

               7)  一个文件或子目录从一个监听目录转移;

               8) 一个新文件或子目录已经在监听目录上创建了;

               9) 一个文件已经在监听目录上被删除了;

              10) 监听文件或目录已经被删除;

              11) 有效监听停止了

              12) 监听文件或目录已被转移,监听正在继续;

         等等...

    接着在抽象主题中定义了一个过滤器——FolderFilter,这个类继承自FileFilter,用来过滤所输入的路径是否为一个目录。最后,抽象主题中还定义了一个线程类,其中用HashMap定义了一个观察者集合和路径集合,利用同步块锁的方式,定义了开始和停止函数。

3、具体观察者实现

public class FileWatcher extends FileObserver {
	FileListener mFileListener;
	Hashtable<Integer, String> mRenameCookies = new Hashtable<Integer, String>();
	public FileWatcher(String path) {
		this(path, ALL_EVENTS);
	}
	public FileWatcher(String path, int mask) {
		this(path, false,mask);
	}
	public FileWatcher(String path, boolean watchsubdir,int mask) {
		super(path, watchsubdir,mask);
	}
	public void setFileListener(FileListener fl){
		mFileListener = fl;
	}
	@Override
	public void onEvent(int event,int cookie,String path) {
		switch (event) {
		......
	}
}

  FileWatcher类继承自之前定义的FileObserver抽象类,包括FileWatcher()函数、setFileListener()函数和onEvent()函数都根据需要进行了重写,根据抽象主题的变化来更新自己。从而实现把给定路径上的文件或目录的状态以此写入日志。

4、结构图示:

 

 只有订阅了文件观测的抽象类,就有了新的文件类型控制,就会发送到订阅者那里,当不想订阅该服务的时候,取消继承也就是不会再接收该服务了。可见,观察者模式有不少的优点:(1)其可以在观察者和被观察者之间建立一个抽象的耦合,被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口;(2)观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知.

由此项目中,不同的FileWatcher观察者可独立运行一个线程,多个观察者共同进行,从而完成不同的共性工作,这点对于比较统一的工作性质有作用,能显著提升效率。

 

posted @ 2018-10-24 23:59  顿学累功  阅读(642)  评论(0)    收藏  举报