【问题标题】:How to create a common interface for various implementations?如何为各种实现创建通用接口?
【发布时间】:2019-06-22 10:16:33
【问题描述】:

我正在做一个小型练习项目,以便在一般情况下进行更多的编程练习。 该项目是一个程序,它获取 CSV 文件的内容并将其放入某个数据库中。 我从创建一个数据库访问接口IDatabaseClient开始,这让我想到了一些事情:

  1. 我的Connect(...) 方法应该是什么样子?各种数据库可能有一组不同的连接所需的凭据,即一个可能需要一个连接字符串,另一个可能需要:URL、用户名、密码等。解决这个问题的一种方法可能是使用 Connect 这样的方法:

任务连接(IConnectionCredentials 凭据);

IConnectionCredentials 接口将为空,每个数据库都有自己的实现,例如:

public class DatabaseNo1Credentials : IConnectionCredentials
{
    public Uri Uri { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
}

我不喜欢这种解决方案的一点是IDatabaseClient 实现的用户没有任何信息应该使用哪个凭证类。如果提供了错误的凭证类,代码将抛出异常。有没有更好的解决方案?

  1. 我的 CSV 文件可能包含不同数据库表的数据。一个 CSV 可能包含 Cars 数据,另一个可能包含 People 数据等。如何使我的 IDatabaseClient 可用于许多数据子集?

我可以这样做:

public interface IDatabaseClient
{
    Task Connect(IConnectionCredentials credentials);
    Task WriteCars(string model, int productionYear);
    Task WritePeople(string firstName, string lastName, int age);
}

但是,如果有一天我想将数据写入 Phones 表或任何其他表怎么办?

【问题讨论】:

  • 一次只能问一个问题吗?
  • @Sweeper 我的问题通常是关于设计好的界面。我举了两个例子来说明为什么我认为我的界面并不完美。无需将其拆分为 2 个问题。

标签: c# oop interface


【解决方案1】:

您的界面在方法方面,尤其是在方法参数方面过于具体。 你不应该有一个带参数的Connect 方法,而是你会做这样的事情:

interface IDatabaseClient
{
    Task ConnectAsync();

    Task AddDataAsync<T>(string databaseName, T data);
}

class DatabaseClient1 : IDatabaseClient
{
    public DatabaseClient1(string username, string password)
    {
        Username = username;
        Password = password;
    }

    public string Username { get;  }

    public string Password { get;  }

    public async Task ConnectAsync()
    {
        // connect using Username and Password
    }

    public async Task AddDataAsync<T>(string databaseName, T data)
    {
        // Not sure if you can work with a generic method for inserting data
        // into your database, but given that you didn't specify your 
        // requirements further, I'm just going to go with this
    }
}

在一个接口中拥有多个数据库表特定操作在我看来违背了拥有一个接口的目的,因此您应该将特定工作委托给其他类,这些类仅依赖于 IDatabaseClient:

class CarManager
{
    public CarManager(IDatabaseClient databaseClient)
    {
        _databaseClient = databaseClient;
    }

    public async Task AddCarAsync(string model, int productionYear)
    {
        var car = new Car(model, productionYear);

        _databaseClient.AddDataAsync("cars", car);
    }

    private readonly IDatabaseClient _databaseClient;
}

【讨论】:

    猜你喜欢
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 2022-11-29
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 2021-06-25
    • 2012-07-24
    相关资源
    最近更新 更多