Наследование интерфейса из базового абстрактного класса и правильного места IDisposable - PullRequest
1 голос
/ 27 марта 2020

У меня следующая структура ниже.

Вопросы:

  • Нужен ли вообще интерфейс IStrategy? Потому что я видел людей, которые делали то же самое, что и я - есть метод Start, который определен как abstract в базовом классе, и они выставили его с помощью интерфейса, который также определяет его. Однако другие люди считают, что достаточно указать метод Start только в базовом классе, и интерфейс вообще не нужен, потому что код усложняется. Каково ваше мнение?
  • Я определяю IBinanceClient и IBinanceSocketClient в базовом классе, и они оба должны быть расположены в какой-то момент. В приведенном ниже коде я реализовал IDisposable в производном классе, но, тем не менее, я думаю, что лучше переместить его в базовый класс, поскольку там определен BinanceClient. Что вы думаете?
public interface IStrategy
{
    public void Start(Bot bot, CancellationToken token);
}

public abstract class StrategyBase : IStrategy
{
    public IBinanceClient Client { get; }
    public IBinanceSocketClient SocketClient { get; }

    protected StrategyBase(string apiKey, string secretKey)
    {
        Client = new BinanceClient(new BinanceClientOptions()
        {
            ApiCredentials = new ApiCredentials(apiKey, secretKey),
            AutoTimestamp = true,
            AutoTimestampRecalculationInterval = TimeSpan.FromMinutes(30)
        });

        SocketClient = new BinanceSocketClient(new BinanceSocketClientOptions()
        {
            ApiCredentials = new ApiCredentials(apiKey, secretKey),
            AutoReconnect = true,
            ReconnectInterval = TimeSpan.FromMinutes(1)
        });
    }

    public List<BinanceStreamTick> Tickers { get; set; }

    // Methods that all strategies use
    public void GetTickers()
    {
        ... implementation
    }

    public abstract void Start(Bot bot, CancellationToken token); // ???
}

public class CompositeStrategy : StrategyBase, IDisposable
{
    public CompositeStrategy(string apiKey, string secretKey) : base(apiKey, secretKey)
    {
    }

    public override void Start(Bot bot, CancellationToken token)
    {
        ... implementation
    }

    private bool _disposed = false;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            if (Client != null)
                Client.Dispose();

            if (SocketClient != null)
            {
                SocketClient.UnsubscribeAll();
                SocketClient.Dispose();
            }
        }

        _disposed = true;
    }
}

Редактировать:

Другой способ, основанный на комментарии @Wiktor Zychla.

public interface IStrategy
{
    public void Start(Bot bot, CancellationToken token);
}

public abstract class StrategyBase : IStrategy, IDisposable
{
    public IBinanceClient Client { get; }
    public IBinanceSocketClient SocketClient { get; }

    protected StrategyBase(string apiKey, string secretKey)
    {
        Client = new BinanceClient(new BinanceClientOptions()
        {
            ApiCredentials = new ApiCredentials(apiKey, secretKey),
            AutoTimestamp = true,
            AutoTimestampRecalculationInterval = TimeSpan.FromMinutes(30)
        });

        SocketClient = new BinanceSocketClient(new BinanceSocketClientOptions()
        {
            ApiCredentials = new ApiCredentials(apiKey, secretKey),
            AutoReconnect = true,
            ReconnectInterval = TimeSpan.FromMinutes(1)
        });
    }

    public List<BinanceStreamTick> Tickers { get; set; }

    public void GetTickers()
    {
        ... implementation
    }

    public abstract void Start(Bot bot, CancellationToken token);

    private bool _disposed = false;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            if (Client != null)
                Client.Dispose();

            if (SocketClient != null)
            {
                SocketClient.UnsubscribeAll();
                SocketClient.Dispose();
            }
        }

        _disposed = true;
    }
}

public class CompositeStrategy : StrategyBase
{
    public CompositeStrategy(string apiKey, string secretKey) : base(apiKey, secretKey)
    {
    }

    public override void Start(Bot bot, CancellationToken token)
    {
        ... implementation
    }
}

1 Ответ

1 голос
/ 27 марта 2020

Нужен ли вам интерфейс IStrategy или нет, зависит от контекста, в котором вы его используете, поэтому неясно. Однако наличие IStrategy с помощью метода Start () и StrategyBase с использованием метода abstract Start() выглядит как дублирование, которое предполагает, что вам нужен только базовый класс.

Относительно того, куда поместить Dispose(), общее правило - объекты должны быть расположены в том же классе, где они созданы. (В том же методе, если это возможно, но это только для очень короткоживущих объектов, а не здесь).

Вы не показываете, где создаются SocketClient и Client, но они объявлено в StrategyBase, что указывает на то, где они должны быть уничтожены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...