Простите, если это наивный вопрос. Предполагается, что interface
скрывает детали реализации, но не обязательно ли она раскрывает аспекты этой реализации из-за того, какие параметры принимают ее методы? Параметры, в которых нуждается метод, неизбежно говорят нам о том, как этот метод выполняет свою функцию.
Это кажется особенно проблематичным в области Inversion Of Control, где компонент более высокого уровня, кажется, «владеет» интерфейсом. Насколько я понимаю, компонент более высокого уровня в основном говорит: мне нужен компонент низкого уровня для выполнения некоторых функций. Вот функции, которые мне нужны (в форме интерфейса), а затем другой класс может предоставить эту услугу бесплатно.
Но как опубликовать этот интерфейс, как компонент верхнего уровня узнает, какие параметры понадобятся разработчику?
И если разработчик идет и изменяет сигнатуры методов интерфейса, то теперь у нас есть сильная связь между интерфейсом и реализацией, которую мы пытались избежать.
Есть ли какая-то абстракция, которая решает эту проблему? Должны ли мы просто «чрезмерно параметризировать» сигнатуры методов в наших интерфейсах и позволить разработчику игнорировать аргументы, которые ему не нужны? Или мы должны всегда иметь параметры no и позволить разработчику иметь дело с получением того, что ему нужно откуда-то еще?
ОБНОВЛЕНИЕ: Позвольте мне привести конкретный пример. Допустим, у меня есть LightController, который реализует интерфейс с методом Detect () или что-то в этом роде. Я компонент "Комната" более высокого уровня, и я хочу, чтобы он включал свет, когда кто-то входит в комнату. Какие параметры я определяю как часть сигнатуры обнаружения? Что, если я передам его в параметр Sound, чтобы источники света могли переключаться в зависимости от уровня звука? Но, черт возьми, есть класс, который хочет реализовать это с помощью обнаружения движения, а не звука. И мне действительно все равно, так или иначе. Так что мне просто нужно пройти через все состояние комнаты и позволить разработчику решить, что ему нужно?
ОБНОВЛЕНИЕ2: Позвольте мне быть более точным с кодом:
interface ILightController {
bool Detect(paramIThinkImplementorWillNeed);
}
class Room {
ILightController lc = GetService(ILightController);
if (lc.Detect(thatParam))
...
}
class MovementLightController : NOTILightController { // nope
public bool Detect(aDifferentParam) {
// i could very well have fulfilled this functionality but the
// interface does not allow for the input i need. that's too bad.
}
}
Я думаю, что одним из решений было бы, если бы "контракт" шел в обе стороны. Что, если вызывающая сторона методов ILightController должна была удовлетворять другой интерфейс, который накладывал ограничения на it , а затем передавал себя каждому методу интерфейса LightController, из которого контроллеры освещения могли бы получить вход, который им нужен. Итак:
interface ILightControllerInput {
public PropertyNeededByImplementorsOfILightController { get; set; }
}
interface ILightController {
public Detect(ILightControllerInput input);
public SomeOtherMethod(ILightControllerInput input);
// etc..
}
class Room : ILightControllerInput {
public PropertyNeededByImplementorsOfILightController { get; set; }
ILightController lc = GetService(ILightController);
if (lc.Detect(this)) ...
}
class MovementLightController : ILightController {
public bool Detect(ILightControllerInput input) {
// that's right baby, it's a 2-way street here. if i'm going to conform
// to your interface, you're going to conform to what i need!
}
}
И затем из этого вы можете получить реализацию служб, которая идет в обе стороны. Компонент более высокого уровня может найти компонент более низкого уровня, который реализует интерфейс, который ему необходим, но компонент более высокого уровня должен указать, какие входные данные он может передавать, и который будет соответствовать подмножеству доступных компонентов низкого уровня (поэтому «удовлетворение потребностей» идет в обе стороны).
Пожалуйста, скажите мне, я курю крэк? Или что-то подобное уже существует (как шаблон и т. Д.)?