Во-первых, ответ Дрю Уиллса абсолютно великолепен - я здесь новичок, и у меня пока нет репутации, чтобы голосовать за него, иначе я бы так и сделал.
К сожалению, и это может быть моим собственным недостатком опыта, я не вижу способа, которым вы собираетесь избежать компромисса между разделением интересов. Кто-то должен знать, какой тип View создать для данного Документа - просто невозможно обойти это.
Как указал Дрю в пункте # 3, вы можете использовать какую-то внешнюю конфигурацию, которая будет указывать вашей системе, какой класс View использовать для какого типа документа. Пункт № 4 Дрю - также достойный путь, потому что, хотя он нарушает принцип Open / Closed (я думаю, что это тот, о котором я думаю), если у вас будет только несколько подтипов Document, с этим наверное не стоит возиться.
Для изменения этого последнего пункта, если вы хотите избежать использования проверок типов, вы можете реализовать фабричный класс / метод, который использует подтипы Map of Document для просмотра экземпляров:
public final class DocumentViewFactory {
private final Map<Class<?>, View> viewMap = new HashMap<Class<?>, View>();
private void addView(final Class<?> docClass, final View docView) {
this.viewMap.put(docClass, docView);
}
private void initializeViews() {
this.addView(Email.class, new EmailView());
this.addView(Letter.class, new LetterView());
}
public View getView(Document doc) {
if (this.viewMap.containsKey(doc.getClass()) {
return this.viewMap.get(doc.getClass());
}
return null;
}
}
Конечно, вам все равно нужно будет редактировать метод initializeViews всякий раз, когда вам нужно добавить новый вид на карту - так что он все еще нарушает OCP - но по крайней мере ваши изменения будут централизованы в вашем классе Factory. а не внутри вашего контроллера.
(Я уверен, что есть много вещей, которые можно настроить в этом примере - валидация, для одного - но это должно быть достаточно хорошо, чтобы получить хорошее представление о том, что я получаю.)
Надеюсь, это поможет.