Если вы хотите эффективно реорганизовать код таким образом, вы должны принять во внимание, что «работа с D1
» и «работа с D2
» должны быть одинаковыми, и должно различаться только поведение; то есть D1 и D2 должны иметь общий «интерфейс» (B<T>
), и вы должны использовать только этот «интерфейс», иначе вы снова начнете использовать спагетти-код повсюду и уродливые приведения.
Если это соответствует вашим потребностям (если нет, то вам следует пересмотреть весь свой подход к проблеме), общий шаблон заключается в том, чтобы просто создать фабричный метод, в котором ваш спагетти-код будет написан только один раз:
public static B<T> CreateD<T>()
{
if (T is A1) return ... //here you can create a new instance of D1 or return a cached one, etc.
else if (T is A2) return ...
}
Вот красивый шаблон, который я люблю использовать, когда потребителю не нужно ничего знать о D1
, D2
и т. д., а нужно знать только о B<T>
:
public class B<T>
{
public B<T> CreateD<T>()
{
if (T is A1) return ... //here you can create a new instance of D1 or return a cached one, etc.
else if (T is A2) return ...
...
}
private B() { } //note constructor is private, consumer can't create a B<T>
private class D1: B<A1> { ... } //private nested types, not visible outside B<T>.
private class D2: B<A2> { ... }
}
Теперь у вас есть абсолютный контроль над тем, сколько Di
может быть реализовано, вы предоставляете один единственный универсальный B<T>
и гарантируете, что всегда возвращаете правильно специализированный тип, фактически не заставляя потребителя что-либо знать об этом.
14.06.2016
B<T>
имеет оD1
илиD2
, которой не было бы, если бы производные классы не были вложенными. 15.06.2016