У меня следующая структура ниже.
Вопросы:
- Нужен ли вообще интерфейс 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
}
}