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

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

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

怎样将.h文件添加到项目中

作为C++的初学者,在运行别人的程序时,第一个遇到的问题就是无法将程序中写到的.h文件包含到项目中来.下面来写一下处理方法.本文以easyx.h为例进行说明 首先右键你的工程 选择Properties选项,然后点击左边的C/C++选项 看到右边的Addtional Include Directories,然后将你的.h文件所在的地址直接粘到后面就好啦!

Windows文件路径转换为java中可识别的文件路径的转义方法,(另附转义多种格式)

ps:欢迎加qq好友:2318645572,交流学习 一:路径转化 Windows中的文件路径格式为 D:\eclipse\apache-tomcat-7.0.67\wtpwebapps\... Java中的文件路径格式为 D:/eclipse/apache-tomcat-7.0.67/wtpwebapps/... 如果直接用windows的路径,用流写入的时候会抛出异常 在java中使用前者则会报错,所以需要先将Windows中的文件路径转换为java中可识别的路径. 作如下处理: Strin

IDEA 相对路径读取项目中的文件

1.目标:想要读取该项目中的resources下的prop文件夹中的text.txt文件 2.实现方法: // 读文件 String path = this.getClass().getClassLoader().getResource("./prop/text.txt").getPath(); FileReader fr = new FileReader(path); BufferedReader br = new BufferedReader(fr); String str = n

项目中观察者模式的应用

目前项目中最多用的模式就是观察者模式了...该模式是当有数据状态变化需要及时通知的时候使用的 项目中其中之一的应用场景: 当网络状态发生变化时影视下载界面提示当前是使用免费的wifi还是机主自己的流量 1.首先定义被观察者的实体类 public class NetworkTypeNotifier extends Observable { //发生变化时调用该方法通知 public void notifyAll(NetworkType networkType) { this.setChanged(

Keyboard项目中观察者模式解析

该项目旨在解决输入框多层嵌套的情况下软盘和输入框位置不适配的问题. 项目的github源码链接为:https://github.com/crazycodeboy/KeyboardObserver/blob/master/KeyboardObserver/KeyboardObserver.m 一.观察者模式实现原理 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.当这个主题对象在状态发生变化时,会通知所有观察者对象,使得他们能够更新自己.在此项目中其实现原理主要体现在

保存文件到当前项目中 适用于项目中的文件上传

1 string f = System.AppDomain.CurrentDomain.BaseDirectory.ToString();//获取项目当前目录 2  3 //保存地址 4 string savePath = "\\files\\网站发布\\" + string.Format("{0:yyyy-MM-dd}", DateTime.Now) + "\\" + fbwzID + "\\" + mTpxx.TPBT +

保存文件到当前项目中

string f = System.AppDomain.CurrentDomain.BaseDirectory.ToString();//获取项目当前目录 //保存地址 string savePath = "\\files\\网站发布\\" + string.Format("{0:yyyy-MM-dd}", DateTime.Now) + "\\" + fbwzID + "\\" + mTpxx.TPBT + ".h

sublime text3 批量查找替换文件夹或项目中的字符

1.点击左上角的"菜单",在弹出的菜单中选择"打开文件夹". 2.在文件夹上右击,选择"在文件夹中查找"选项 3.之后会软件底部会弹出对话框,分别输入要查找的内容和替换的内容,最后点击替换按钮 4.再然后会弹出总共要替换多少处的提示,点击确定按钮即可 5.最后一步很重要,就是"保存全部". 原文地址:https://www.cnblogs.com/-mrl/p/8659113.html

Eclipse 中 Java 项目中 .settings 文件夹作用

今天工作时,因对 .settings 文件夹误操作,耗时 6 个多小时,才了解到原因就出在 .settings 文件夹.经查阅资料,对 .settings 做如下整理: 就如setting这个名字,就是存放存放各种插件的配置文件..有这些文件的约束你可以更好的利用IDE进行coding.所以呢,这些文件只是用来配置环境用的. 1. org.eclipse.jdt.core.prefs 该文件是与Compile相关的配置,一般情况下的内容如下: 可以手动修改该文件,添加一些其他的配置,然后重启Ec