Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用CRUD静态方法的观察者模式和DAO类_Java_Dao_Observer Pattern - Fatal编程技术网

Java 使用CRUD静态方法的观察者模式和DAO类

Java 使用CRUD静态方法的观察者模式和DAO类,java,dao,observer-pattern,Java,Dao,Observer Pattern,我正在回顾一些DAO类,它们将CRUD静态方法create()、delete()等公开给程序,每个DAO类通过Notification.java类检查数据库中的更改,以及是否通过从数据库中提取对象接收到一个更改通知来实现观察者模式 简化代码与此类似: java public class OfficeDAO implements PropertyChangeListener { public OfficeDAO() { /* * Below we

我正在回顾一些DAO类,它们将CRUD静态方法create()、delete()等公开给程序,每个DAO类通过Notification.java类检查数据库中的更改,以及是否通过从数据库中提取对象接收到一个更改通知来实现观察者模式

简化代码与此类似:

java

public class OfficeDAO implements PropertyChangeListener
{
    public OfficeDAO()
    {
        /* 
         * Below we add ourselves to the observers of class Notifications
         * (see observer pattern in Java) in practice we are notified
         * when one of our objects is changed by a remote client user
         */
        Notification.addChangeListener(this);
    }

    public static void create(Office office)
    {
      Connection connection = DBConnection.getConnection();

      //... stuff with the database insertion

      Notification.notifyDatabaseChanges("ocreate-" + officeId);
    }
}
现在的问题是addChangeListener(这个);在构造函数中,但由于此DAO类通过其静态方法使用,因此从未调用构造函数

要在应用程序的main()方法(顺便说一下,在EDT线程内)中修复此问题,有如下调用:

new OfficeDAO(); //ignore this, it is needed only to start the DAO constructor
这似乎有点骇人,所以我想添加一个

static {
  Notification.addChangeListener(this);
}
在OfficeDAO.java类中,但“this”引用当然不存在于静态初始值设定项中,因此我没有解决方案。 从DAO方法中删除静态是毫无疑问的,因为这些方法在整个应用程序中都被调用,并且在没有类实例的情况下被调用


有没有我目前缺少的干净的解决方案或解决方法?

这似乎是一个相当混乱的场景,创建一个新对象只是为了向通知添加一个侦听器更像是一种反模式。我的假设是,这是一些遗留代码的一部分,不可能进行太多的代码重分解。我可以说,由于DAO层的行为更像一个单例,因此可以嵌入一个预先创建的DAO实例,并通过静态引用访问它

private static OfficeDAO myDAO = new OfficeDAO(); //The constructor code remains the same

您可以将所有DAO类更改为Singleton。我同意不需要创建DAO实例,因为DAO没有状态,这不是理想的解决方案。但同样,您并不是在寻找一个理想的解决方案,而是一个更干净的黑客,只需对客户端代码进行最小的更改。我不确定您是否在项目中使用了IoC框架,但如果您决定在将来使用IoC框架,将DAO转换为Singleton将为同样的工作奠定基础

让我们将OfficeDAO转换为单例:

public class OfficeDAO implements PropertyChangeListener {

    private static volatile OfficeDAO INSTANCE;

    private OfficeDAO() {
        if (INSTANCE != null) {// prevent reflection attacks
            throw new InstantiationError("Illegal attempt to create more than one instance of OfficeDAO");
        }
        Notification.addChangeListener(this);
    }

    public static OfficeDAO getInstance() {
        OfficeDAO localInstance = INSTANCE;
        if (INSTANCE == null) {
            synchronized (OfficeDAO.class) {
                localInstance = INSTANCE;
                if (localInstance== null) {
                    INSTANCE = localInstance = new OfficeDAO();
                }
            }
        }
        return localInstance;
    }

    public void create(Office office) {
        Connection connection = DBConnection.getConnection();

        // ... stuff with the database insertion

        Notification.notifyDatabaseChanges("ocreate-" + officeId);
    }
}
如果以类似的方式更改所有DAO,那么在客户端代码中唯一需要做的更改就是将
ClassName.staticMethod()
更改为
ClassName.getInstance().staticMethod()

示例:
OfficeDAO.getInstance().create(..)

*也就是说,您的观察者似乎也是主题,这不是实现观察者模式的经典方式。此外,您还可以避免双重检查锁定,并求助于未延迟实例化的单例。如何实现Singleton是您的选择,与问题没有直接关系

如果您的项目开始使用诸如Spring或Guice之类的Ioc框架,那么您可以去掉私有构造函数和getInstance方法。那么,您最好将DAO中的所有静态方法更改为实例方法,并让IoC框架创建DAO并将其注入所有需要它们的类中。这有几个优点:

  • 大多数IoC框架允许您决定在请求时是否只提供类的一个对象,或者每次请求一个对象时是否提供一个新对象。因此,您可以在单例DAO和非单例DAO之间进行选择,而无需更改DAO
  • 您的数据源可以从数据库更改为.csv文件,而不必更改使用DAO的客户机代码
  • 实际上,您可以在服务类中模拟DAO进行单元测试

  • DAO设计是一个非常复杂的主题,您可以开始阅读Balusc(本论坛的用户)的文章,最后选择一个处理DAO和连接管理的框架

    一个非常精简的库为您提供了正确DAO实现的良好开端,它将为您创建DAOFactory并管理连接,而无需导入100MB Spring或Hibernate jar库

    至于为数据库操作添加侦听器和通知程序,您应该完全避免这种情况,而是使用支持事件通知的数据库,如Oracle或Firebird


    这样,您只侦听事件,数据库会通知您对其表的任何更改。

    PropertyChangeListener是否也只包含在每个DAO中重新定义的静态方法?能否显示PropertyChangeListener和通知类的代码?此外,在经典的观察者模式中,是观察者通知观察者其状态发生了变化。是的,这是一些遗留代码,如果我确信方法是相当多的DAO,并且项目本身相当大,则可以重构这些代码。如果我将DAO设置为静态,我将破坏通知。addChangeListener(this);调用对应用程序正常工作至关重要。@sarah.ferguson我认为不需要将DAO的
    设置为静态。这个答案旨在解释的是,您可以对DAO进行
    静态
    引用,而不只是说
    newDAO()
    ;虽然这会使代码看起来不那么可怕,但肯定会适得其反。为什么使用类的引用访问静态方法?你的IDE会在你的代码中添加关于这一点的警告。好吧,singleton是一个不太黑的解决方案,但我想提供一个“干净”的解决方案,因为我会搞乱很多类。“双重检查锁定”是什么意思?观察者不能也是一个主体吗?这是一种反模式吗?@sarah.ferguson您将进行的更改量与您的代码的黑客程度成反比。在我的解决方案中,您将要处理大量的类,但是除了客户机代码访问方法的方式之外,您不会在真正意义上做太多的更改。您可以阅读有关双重检查锁定的更多信息。您不需要以这种方式实现单例。在网站上搜索不同的内容