API 的 C# 重构 Facade

C# refactoring Facade for API

我为我的应用程序创建了一个 dll。我正在使用 Facade design pattern 封装 API,因为他们的决定让一些程序员(不是我的组织)感到不舒服。

他们的 API 是这样工作的:

  1. 初始化 DiadocApi 对象
  2. 获取令牌的授权

为了初始化 DiadocApi 对象,我需要 developerKey(获取订阅)。 对于授权我需要 login, password.

我的决定很糟糕,因为它是一个单例,我需要进行单元测试。我可以更改我的代码吗?

//I GET IT FROM NUGET PACKAGE
using Diadoc.Api;

public sealed partial class DiadocApiFacade
{
    private static readonly object _mutex = new object();

    private static DiadocApiFacade _instance;
    private string _token;
    private DiadocApi _api;

    private DiadocApiFacade() { }

    public static string DefaultUrl => "url was here";
    public string DefaultFromBoxId { get; set; }
    public DiadocApi Api { get => _api; private set => _api = value; }
    
    public static DiadocApiFacade GetInstance()
    {
        if (_instance == null)
        {
            lock (_mutex)
            {
                if (_instance == null)
                {
                    _instance = new DiadocApiFacade();
                }
            }
        }
        return _instance;
    }

    public string Authenticate(string login, string password, string privateDeveloperKey)
    {
        if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(developerKey))
            throw new ArgumentNullException();

        Api = new DiadocApi(developerKey, DefaultUrl, new WinApiCrypt());

        return _token = _api.Authenticate(login, password);
    }

    //method for example, >60% methods like that
    public Document GetDocument(string messageId, string documentId, string boxId = null)
    {
        return _api.GetDocument(_token, boxId ?? DefaultFromBoxId, messageId, documentId);
    }
}

我假设您想对消耗 DiadocApiFacade.

您的 代码进行单元测试

依赖倒置来拯救!用接口抽象你的DiadocApiFacade。使用 工厂模式 来创建对象。下面是一个简单的示例,但如果您需要外观以某种方式运行(例如设置 class 以更改它连接到的位置),您可以扩展工厂。

GetOrCreate 将 return 相同的实例,但如果您在项目中使用依赖项 injection framework(有许多可能满足您的需求),请改用它。

public interface IDiadocApiFacade
{
    string Authenticate(string login, string password, string privateDeveloperKey);
    public Document GetDocument(string messageId, string documentId, string boxId);
    public Document GetDocument(string messageId, string documentId);

}

public class DiadocApiFacadeFactory
{
    private static IDiadocApiFacade? _instance = null;

    public IDiadocApiFacade Create() //Add parameters 
    {
        return new DiadocApiFacade();
    }

    public IDiadocApiFacade GetOrCreate()
    {
        if(_instance == null)
            _instance = Create();

        return _instance;
    }
}

public sealed partial class DiadocApiFacade : IDiadocApiFacade
{
    internal DiadocApiFacade() { }

    public string Authenticate(string login, string password, string privateDeveloperKey) => string.Empty;
    

    public Document GetDocument(string messageId, string documentId)
        => GetDocument(messageId, documentId, null);

    public Document GetDocument(string messageId, string documentId, string? boxId) => new Document();
    
}

然后你可以使用 [moq)[https://www.nuget.org/packages/moq/] 进行单元测试并伪造 IDiadocApiFacade[=16 的实现=]