【问题标题】:More flexible factory更灵活的工厂
【发布时间】:2012-12-22 19:43:16
【问题描述】:

我目前正在为学校做一个小项目。在我的 Java 应用程序中,我需要一个数据库,并且我想让我的应用程序能够使用不同类型的数据库。所以我目前实现了一个 txt 数据库和一个 PostgreSQL。将来,应该可以添加其他数据库类型。像 XML 或 MySQL,...

为了创建一个数据库实例,我设计了一个使用枚举的工厂。它工作得很好,但在我的opionio中它并不是真正的灵活。所以,我做了一些研究,但没有找到一个对我来说很清楚的好例子。

这是我的枚举:

public enum DatabaseType {
    TXT,
    SQL,
    XML;
}

这是我的工厂:

public class DatabaseFactory {      

    public Database createDatabase(DatabaseType type, String databaseName) throws DatabaseException {
        if(type.equals(DatabaseType.TXT)) {
            return new FileDatabase(databaseName);
        }else if(type.equals(DatabaseType.SQL)) {
            return new SQLDatabase(databaseName);
        }else if(type.equals(DatabaseType.XML)) {
            return new XMLDatabase(databaseName);
        }else {
            //default
            return new FileDatabase(databaseName);
        }
    }
}

我的目标是将来只编辑枚举,而不涉及工厂本身。这应该给我足够的灵活性,但我不知道我该怎么做。

【问题讨论】:

  • 一种选择是将它放在枚举本身中。
  • @DaveNewton,我猜你还需要 if-else-if 或 switch-case 结构吗?
  • 否,例如,请参阅 Mattias 的回答,或者将枚举映射到一个简单的工厂(如果您有时需要额外的逻辑,那就太好了)等等。您可以使用 if -声明。

标签: java enums factory


【解决方案1】:

您可以将工厂放在enum 本身中。

public enum DatabaseType {
    TXT {
        @Override
        public Database createDatabase(String databaseName) {
            return new FileDatabase(databaseName);
        }
    },
    SQL {
        @Override
        public Database createDatabase(String databaseName) {
            return new SQLDatabase(databaseName);
        }
    },
    XML {
        @Override
        public Database createDatabase(String databaseName) {
            return new XMLDatabase(databaseName);
        }
    };

    public abstract Database createDatabase(String databaseName);
}

在 Java 中,enums 不仅仅是整数值的好名字(就像在 C 中一样)。将enum 视为具有固定数量实例的类的更好方法。结合匿名类的概念,您可以为枚举中的每个值赋予特定于该值的不同属性和方法。

【讨论】:

    【解决方案2】:

    使用反射:

    您的枚举:

    public enum DatabaseType {
        FILE(FileDatabase.class),
        SQL(SQLDatabase.class);
    
        private Database db;
    
       DatabaseType(Class<Database> db) {
          this.db = db;
       }
    
       /*package friendly*/ Class<Database> getDatabase() {
          return this.db;
       }
    }
    

    您的工厂:

    public class DatabaseFactory {
    
        public static Database create(DatabaseType type, String dbName) throws Exception {
           Database db = null;
           Constructor cons = type.getDatabase().getDeclaredConstructor(new Class[] { String.class });
           cons.setAccessible(true);
           db = cons.newInstance(dbName);
    
           return db;
        }
    
    }
    

    您的数据库实施者:

    public class FileDatabase extends Database {
    
        /* can only be instantiated via reflection */
        private FileDatabase(String databaseName) {
            // init db.
        }
    }
    

    【讨论】:

    • 好的,但我还是不明白如何获得数据库实例? (我已经有了一个接口,实际上是一个抽象类)。
    • 我添加了一个使用反射的示例。请注意,这是未经测试的代码。
    猜你喜欢
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-11
    相关资源
    最近更新 更多