У нас есть ряд классов, которые происходят из единого набора интерфейсов, таким образом что
IFoo-> BasicFoo, ReverseFoo, ForwardFoo
IBar -> UpBar, DownBar, SidewaysBar
IYelp -> Yip, Yap, Yup
где конструктор для Нечто похож Foo(IBar, IYelp)
Эти объекты используются в течение проекта.
Там существует другой класс, который имеет метод, подпись которого public double CalcSomething(IFoo, IAnotherClass)
это применяется в какой-то момент к каждому Foo. Нам спустились с запроса выше того конкретный объектный состав, скажем, a BasicFoo(UpBar,Yip)
, используйте другой алгоритм кроме того, найденного в CalcSomething
.
Мой первый инстинкт должен был сказать, давайте изменим интерфейс IFoo, таким образом, мы можем спустить логику к уровню класса Foo, изменить конструктора, чтобы быть Foo(IBar, IYelp, IStrategy)
и затем имейте объекты Foo, инкапсулируют эту логику. К сожалению, нам также сказали, что дизайн архитектуры предусматривает что там не быть никакими зависимостями между IFoo
, это - реализации и IAnotherClass
. Они непреклонны по отношению к этому.
Хорошо, уверенный, тогда я думал, что мог бы использовать шаблон "посетитель", но... как? Смысл создания состава был то, так, чтобы никакой другой класс не видел детали реализации. Отражение для взгляда в объектах, полностью повреждая инкапсуляцию? О, ад нет.
Таким образом, я приехал сюда, потому что я в замешательстве. У кого-либо есть какие-либо предложения, как мы могли рассматривать особый случай одного из составов, не изменяя состав или повреждая инкапсуляцию? Должно быть простое решение, которое я пропускаю.
Править:
Удаленное незаконное начало. Измененный "обработанный особенно" в более описательное значение.
A Расчетные продукты
, которые выбирают соответствующий алгоритм, основанный на типе IFOO
, вы предоставляете, решат проблему (за счет условного):
interface ICalcSomethingStrategy {
public double CalcSomething(IFoo, IAnotherClass);
}
CalcSomethingStrategyFactory {
ICalcSomethingStrategy CreateCalcSomethingStrategy(IFoo foo) {
// I'm not sure whether this is the idiomatic java way to check types D:
if (foo.Bar instanceof UpBar && foo instanceof Yip) {
return new UnusualCalcSomethingStrategy();
} else {
return new StandardCalcSomethingStrategy();
}
}
}
В духе поцелуя я бы добавил метод Isspecial () к IFOO, и использовать это, чтобы решить, какой алгоритм использовать в калькуле ().
Это предполагает, что это единственный особый случай.
нет никакого пути к calcSomething, чтобы не нуждаться в знании, чтобы сделать "специальное" поведение, но кроме которого, можно поддержать большую часть инкапсуляции этот путь.
Создают интерфейс IQualifyForSpecialTreatment маркера, который расширяет IFoo. Расширить BasicFoo до SpecialBasicFoo и иметь его, реализуют IQualifyForSpecialTreatment.
interface IQualifyForSpecialTreatment extends IFoo {
}
class SpecialBasicFoo extends BasicFoo implements IQualifyForSpecialTreatment {
...
}
можно затем добавить другой аромат calcSomething:
calcSomething (IQualifyForSpecialTreatment foo, IAnotherClass whatever) {
... perform "special" variant of calculation
}
calcSomething (IFoo foo, IAnotherClass whatever) {
... perform "normal" variant of calculation
}