工厂更灵活

时间:2012-12-22 19:43:17

标签: java enums factory

我目前正在为学校做一个小项目。在我的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);
        }
    }
}

我的目标是仅在将来编辑枚举,而不会触及工厂本身。这应该给我足够的灵活性,但我不知道如何做到这一点。

2 个答案:

答案 0 :(得分:3)

您可以将工厂放在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中,enum不仅仅是整数值的好名称(如C中所示)。考虑enum的更好方法是具有固定数量实例的类。与匿名类的概念一起,您可以为枚举中的每个值赋予特定于该值的不同属性和方法。

答案 1 :(得分:1)

使用反射:

你的枚举:

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.
    }
}