数据库管理器类的设计模式

时间:2016-06-02 16:20:10

标签: java database design-patterns

我实现了一个类Database Manager来管理两个数据库引擎上的操作。该类有一个私有变量databaseEngine,它在使用类方法(删除数据库,创建数据库,运行脚本,比较,断开连接等)之前设置,并且基于此变量,类可以识别如何表现。

然而,我知道这是错误的,Database Manager的方法充满了像这样的开关案例:

public void CreateNewDatabase(String databaseName){

switch (databaseEngine){
  case "mysql":
      //Executes a prepared statement for dropping mysql database (databaseName
  break;
  case "postgres":
      //Executes a prepared statement for dropping postgres database (databaseName
  break;
...
    }
}

我需要一个很好的建议。我想加载配置和资源文件夹中的所有内容,我的意思是,准备好的创建和删除语句等等。如果需要支持新的数据库引擎,它将不会令人头疼,因为它只需要保存sql sripts在资源文件和配置文件中的任何其他数据。 请建议我对此案例有用的任何设计模式。

5 个答案:

答案 0 :(得分:1)

每当需要基于switch语句调用不同的操作时,请考虑使用定义操作接口的抽象类和实现该操作的实现类。

在您的情况下,databaseEngine是一个命名数据库的String。而是创建一个抽象类DatabaseEngine并定义像createDatabase

这样的操作
 public abstract class DatabaseEngine {
      public abstract void createDatabase(String databaseName);
      public abstract void dropDatabase(String databaseName);
 }

并添加实现:

public class PostgresEngine extends DatabaseEngine {
     public void createDatabase(String databaseName) { 
         ... // do it the postgres way
     }   
}

然后在您的经理类

中使用它
public void createNewDatabase(String databaseName) {
     engine_.createDatabase(databaseName);
}

答案 1 :(得分:1)

第一件事:打开琴弦是如此古老的学校;如果有的话你会想要使用真正的枚举。但当然,这不是重点;切换枚举与从“OO设计”的角度切换字符串(关于你想到的东西)一样糟糕。

从OO的角度来看,wero的解决方案绝对是“正确的选择”。你看,好的OO设计始于SOLID;和SOLID以SRP开头。

在这种情况下,我会指出“改变SRP的方面只有一个原因”。事情是:如果你将2,3个,n个不同数据库的所有数据库处理推送到一个类......这意味着如果你的任何数据库需要更改,你必须更改那个类。除了显而易见的事实:为一个数据库提供“访问手段”(几乎更多),而不是单个类的“单一责任”。

另一种观点:这是关于平衡的。要么你对一个好的,结构良好的,“真正的OO类型”设计感兴趣...那么你必须咬紧牙关并定义一个接口或抽象基类;然后针对每个具体数据库实施/扩展。

或者您更喜欢“将所有东西都塞进一个班级”......然后保留您所拥有的东西,因为如果您使用由金或钢制成的门把手真的无关紧要......对于建造的房屋而言无论如何,在一个糟糕的地下室。

含义:您的switch语句只是设计不太理想的结果。现在决定是否要治愈症状或问题的根本原因。

答案 2 :(得分:1)

  

我实现了一个类数据库管理器,它管理两个数据库引擎上的操作。

如果您有三个或四个或五个不同的数据库/存储怎么办?例如,Oracle,MongoDB,Redis等。您是否仍然将所有这些实现都放入Database Manager

  

数据库管理器的方法充满了切换案例......

正如所料,因为你把所有东西放在一个班级里。

  

请建议我对这种情况有用的任何设计模式。

简化解决方案最简单的方法是将MySQLPostgree实现彼此分开。您需要使用 Factory 策略设计模式。如果有人看到一个开关,就应该考虑使用它们,但不要沉迷于模式。它们不是你的目标,即不要因为你可以将它们放在代码中的任何地方。

所以,你应该从定义你的抽象开始。如果所有数据库子类都有共同的功能,则创建一个接口或一个抽象类。

// I'm not sure what methods you need, so I just added methods you mentioned.
public interface MyDatabase {
    void drop();
    void create();
    void runScript();
    void compare();
    void disconnect();
}

然后你需要实现数据库,实际上是策略

public final class MySqlDatabase implements MyDatabase {
    @Override
    public void drop() {}
    ...
}

public final class PostgreDatabase implements MyDatabase {
    @Override
    public void drop() {}
    ...
}

最后,您需要创建工厂。如果您愿意,可以将其设置为静态或实现接口。

public class MyDatabaseFactory {
    public MyDatabase create(String type) {
        switch (type) {
        case "mysql":
            return new MySqlDatabase();
        case "postgress":
            return new PostgreDatabase();
        default:
            throw new IllegalArgumentException();
        }
    } 
}

您不一定要传递字符串。它可以是一个选项/设置类,但它们有增长的趋势,这可能导致膨胀的类。但是不要过于担心,这不是你目前最大的问题。

最后,但并非最不重要。如果您不介意,请修改您的命名约定。请don't name your classes as managers or helpers

答案 3 :(得分:0)

您可以为您的DatabaseEngines创建一个抽象基类,如下所示:

public abstract class DatabaseEngine {

    public abstract void createDatabase(final String databaseName);

    public abstract void dropDatabase(final String databaseName);
}

然后为您支持的每个DatabaseEngine创建具体实现:

public final class MySQLEngine extends DatabaseEngine {

    @Override
    public void createDatabase(final String databaseName) {
    }

    @Override
    public void dropDatabase(final String databaseName) {
    }
}

然后,当你想要创建/删除它时,它看起来会更像这样:

databaseEngine.createDatabase("whatever");

答案 4 :(得分:0)

这是基于意见的问题:但在我看来,你可以使用:

  1. Factory Design pattern.这将照顾任何其他人 数据库将来添加或更改。
  2. 示例:

    public interface IDataBaseEngine {
        ...
    }
    
    public class OracleDBConnection implements IDataBaseEngine {
        ...
    }
    
    public class MySQLDBConnection implements IDataBaseEngine {
        ....
    }
    
    public class DatabaseEngineFactory {
        public IDataBaseEngine getDatabaseConnection() {
            ....
        }
    }
    
    1. 其次,创建文件让我们说xml文件将包含您的SQL 并根据您的数据库(可以配置)这些文件 转换为SQL
    2. 示例:

        

      SQL文件: customer.table

      <TABLE>
          <SELECT>
              <FROM>customer</FROM>
              <WHERE>customer_id = ?</WHERE>
              <ORDER_BY>customer_id<ORDER_BY>
          </SELECT>
      </TABLE>
      

      现在,如果您的配置文件说您的数据库是oracle,那么在编译上面的SQL文件时,它将创建以下SQL文件:

      SELECT * FROM customer
       WHERE customer_id = ?
       ORDER BY customer_id