文件路径监控项目中观察者模式的分析

Posted haoyj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文件路径监控项目中观察者模式的分析相关的知识,希望对你有一定的参考价值。

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、效果

  • 可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
  • 在观察目标和观察者之间建立一个抽象的耦合。 
  • 支持广播通信。
  • 符合“开闭原则”的要求。

以上是关于文件路径监控项目中观察者模式的分析的主要内容,如果未能解决你的问题,请参考以下文章

设计模式 行为型模式 -- 观察者模式(发布-订阅(Publish/Subscribe)模式)

otto源代码分析

天气预报项目中的观察者模式分析

验证码自动填充项目中观察者模式分析

爬虫项目clwaer_news 观察者模式分析

设计模式在实际开发中的应用