首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >适配器设计模式和外观设计模式的实现

问适配器设计模式和外观设计模式的实现
EN

Stack Overflow用户
提问于 2022-11-07 20:35:18
回答 1查看 55关注 0票数 2

我刚开始设计图案。我正在实现一个工具,它可以根据用户的需要连接到不同的数据库。这是我的代码结构。

​

​

在控制器中,我有API调用。下面我粘贴用于获取服务器中所有数据库的post APi调用

代码语言:javascript
复制
 @PostMapping("/allDatabases")
    public List<String> getDatabases(@RequestBody DatabaseModel db) 
        throws IOException, SQLException {
        
        return migrationInterface.getAllDatabases(db);
         

    }

现在,我通过在服务包中调用接口中的方法来获得响应。但是,当数据库服务器发生变化时(例如: postgres、mysql),我必须使用不同的查询。

例如:

代码语言:javascript
复制
public class PostgresPreparedStatements {

    public PreparedStatement getAllDbs(Connection con) throws SQLException {
        
    return con.prepareStatement(
        "SELECT datname FROM pg_database 
             WHERE datistemplate = false;");
    }
    
    
}

此查询在MySQL数据库中不起作用。因此,我将为不同的数据库保留不同的准备语句。我的想法是从控制器调用BaseAdapter并检查服务器类型,如下所示。

代码语言:javascript
复制
public class BaseAdapter {
    
    public void checkServerType(String server) {
        
        switch(server) {
            case "postgres" :
//               postgres functions
                break;
            case "mysql" :
//              mysql functions
                break;
            default: 
                break;
        }   
    }

}

如果服务器是postgres,我想调用PostgresConnector.java。在Connector中,我想调用Facade来调用函数和相关查询。

知道怎么做吗?

请注意:目前我正在为postgres和MySQL实现这一功能,但是在将来,这将适用于任何数据库。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-08 17:08:14

当您想要添加新的行为(例如在您的情况下的新数据库)时,不使用适配器模式。适配器类的目标是允许其他类访问现有的功能。适配器将一个类的接口转换为另一个类可能使用的东西。

看起来,BaseAdapter有责任为不同的数据库选择SQL语句。我们可以解释这一责任,就像我们希望生成基于数据库的SQL查询一样。因此,看起来我们可以将这个switch语句替换为HashTable(Java)或Dictionary(C#)。而且这个HashTable(Java)或Dictionary(C#)可以是一个创建SQL查询的简单工厂。我们生成的SQL查询可以作为具体数据库的策略。

那么让我们开始研究代码吧。

看起来这是一个可以使用战略模式的地方:

策略模式是一种行为软件设计模式,允许在运行时选择算法。代码不是直接实现单一的算法,而是接收在一系列算法中使用的运行时指令。

让我通过C#展示一个例子。我很抱歉我不是Java人,但是我提供了关于代码在Java中的外观的评论。

我们需要有一些共同的行为,这些行为将在所有的战略中共享。在我们的例子中,它只是来自不同数据提供者的一个GetAllDbs()方法:

代码语言:javascript
复制
public interface IDatabaseStatement
{
    IEnumerable<string> GetAllDbs();
}

以及它的具体实现。这些是可交换的战略:

代码语言:javascript
复制
public class PostgresDatabaseStatement : IDatabaseStatement // implements in Java
{
    public IEnumerable<string> GetAllDbs()
    {
        return new [] { "PostgresDatabaseStatement" };
    }
}

public class MySQLDatabaseStatement : IDatabaseStatement // implements in Java
{
    public IEnumerable<string> GetAllDbs()
    {
        return new[] { "MySQLDatabaseStatement" };
    }
}

public class SqlServerDatabaseStatement : IDatabaseStatement // implements in Java
{
    public IEnumerable<string> GetAllDbs()
    {
        return new[] { "SqlServerDatabaseStatement" };
    }
}

我们需要一个可以储存所有策略的地方。我们应该能从这家商店得到必要的策略。这是一个可以使用简单工厂的地方。简单的工厂不是工厂方法模式,也不是抽象工厂。

代码语言:javascript
复制
public enum DatabaseName
{
    SqlServer, Postgres, MySql
}

public class DatabaseStatementFactory
{
    private Dictionary<DatabaseName, IDatabaseStatement> _statementByDatabaseName
        = new Dictionary<DatabaseName, IDatabaseStatement>()
        {
                { DatabaseName.SqlServer, new SqlServerDatabaseStatement() },
                { DatabaseName.Postgres, new PostgresDatabaseStatement() },
                { DatabaseName.MySql, new MySQLDatabaseStatement() },
        };

    public IDatabaseStatement GetInstanceByType(DatabaseName databaseName) =>
        _statementByDatabaseName[databaseName];
}

然后,您可以更容易地获得所需存储的实例:

代码语言:javascript
复制
DatabaseStatementFactory databaseStatementFactory = new();
IDatabaseStatement databaseStatement = databaseStatementFactory
    .GetInstanceByType(DatabaseName.MySql);
IEnumerable<string> allDatabases = databaseStatement.GetAllDbs(); // OUTPUT: 
    // MySQLDatabaseStatement 

此设计与开放/封闭原则兼容。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74352647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档