Справочная информация: я разрабатываю систему обмена сообщениями. Эта структура позволит:
- отправка сообщений через сервисную шину
- подписка на очереди в шине сообщений
- подписка на темы в шине сообщений
В настоящее время мы используем RabbitMQ, но я знаю, что мы перейдем на Microsoft Service Bus (в Premise) в самое ближайшее время.
Я планирую создать набор интерфейсов и реализаций, чтобы при переходе на ServiceBus мне просто нужно было предоставить новую реализацию без внесения каких-либо изменений в код клиента (т. Е. Издателей или подписчиков).
Проблема в том, что RabbitMQ и ServiceBus не могут быть переведены напрямую. Например, RabbitMQ опирается на биржи и имена тем, а ServiceBus - это пространства имен и очереди. Также нет общих интерфейсов между клиентом ServiceBus и клиентом RabbitMQ (например, оба могут иметь IConnection, но интерфейс отличается - не от общего пространства имен).
Итак, на мой взгляд, я могу создать интерфейс следующим образом:
public interface IMessageReceiver{
void AddSubscription(ISubscription subscriptionDetails)
}
Из-за непереводимых свойств двух технологий реализации ServiceBus и RabbitMQ вышеприведенного интерфейса предъявляют различные требования. Так что моя реализация RabessMq для IMessageReceiver может выглядеть так:
public void AddSubscription(ISubscription subscriptionDetails){
if(!subscriptionDetails is RabbitMqSubscriptionDetails){
// I have a problem!
}
}
Для меня вышеприведенная линия нарушает правило замещаемости Лискова.
Я подумал об этом, чтобы подписка приняла IMessageConnection, но опять-таки для подписки RabbitMq потребовались бы определенные свойства RabbitMQMessageConnection.
Итак, мои вопросы:
- Я прав, что это нарушает LSP?
- Согласны ли мы с тем, что в некоторых случаях это неизбежно или я что-то упускаю?
Надеюсь, это понятно и по теме!
interface IMessageReceiver<T extends ISubscription>{void AddSubscription(T subscriptionDetails); }
. Реализация может выглядеть так public class RabbitMqMessageReceiver implements IMessageReceiver<RabbitMqSubscriptionDetails> { public void AddSubscription(RabbitMqSubscriptionDetails subscriptionDetails){} }
(в Java).
interface TestInterface<T extends ISubscription>
бы ясно показывает, какие типы принимаются, и что есть различия между реализациями.