Объектно-ориентированный дизайн: общая обработка подклассов, которые вводят новые поля

Это проблема дизайна, с которой я постоянно сталкиваюсь, поэтому я подумал, что наконец-то выложу ее и посмотрю, как люди подойдут к ней. Проблема заключается в следующем:

Я определяю определенный класс, который по большей части описывает все экземпляры объектов, которые я буду использовать, как по поведению, так и по данным. Это здорово и хорошо работает для базовых объектов. Затем появляются объекты другого типа, которым требуются те же данные и поведение, но, кроме того, хотелось бы иметь дополнительное поле здесь и там или дополнительную структуру данных.

Назовем класс Something :

public class Something {
    private int id;
    private String fieldA;
    private String fieldB;
    private List list;

    // Then we have getters, setters, and some base methods
}

Иногда нам нужно использовать SomethingElse и SomethingDifferent . Они на 90% похожи на Что-то в том, что их описывают одни и те же данные и поведение, однако каждое из них дополнительно имеет дополнительные поля, которые должны использоваться остальной частью программы:

public class SomethingElse extends Something {
    private String dataSpecificToSomethingElse;
    // Then we have getters, setters, and some new-data specific methods
}

public class SomethingDifferentextends Something {
    private List dataSpecificToSomethingDifferent;
    // Then we have getters, setters, and some new-data specific methods
}

Я хотел бы подойти с приличным способом обработки семейства объектов Something обычным объектно-ориентированным способом, поскольку я не хотел бы связывать остальную часть моего приложения с конкретными деталями реализации (потому что нам может потребоваться добавить SomethingWacky позже). Я не хочу иметь дело с подклассами напрямую, так как это нарушает полиморфизм и, вероятно, будет включать в себя необходимость понижения / переключения типа - фу.

Я могу придумать следующие подходы для решения этой проблемы:

  1. Создайте абстрактный базовый класс, который определяет все методы для семейства Something . Затем дочерние элементы реализуют только то поведение, которое они хотят обеспечить, оставляя NOP / пустое переопределение для методов, которые не вызывают беспокойства. Это позволяет обрабатывать все одинаково, но приводит к раздуванию интерфейса.
  2. Переместите ответственность на базовый класс с помощью общих рабочих методов, следуя Говори, не спрашивай . Например, это могут быть такие вещи, как display (), doWork (), persist (), getStateFromDisplay () и т. Д. Каждый подкласс будет принимать во внимание свои данные при переопределении этих базовых методов. Недавно я прочитал статью Аллена Холуба, в которой говорилось, что что-то подобное может быть хорошей практикой. Кажется, что это переносит слишком большую ответственность за внешние проблемы на класс.
  3. Создайте своего рода класс данных, который группирует все дополнительные данные / поведение из подклассов, и обратитесь к этому в Something . Это не очень похоже на OO.

Я использовал подход 1 в предыдущем проекте - но в этом случае, хотя каждый подкласс реализовал / переопределил только те методы, о которых он заботился, операции были на самом деле достаточно общими, поэтому было правдоподобно, что класс мог бы согласованно реализовать все или только некоторые.

Каждый подход кажется чем-то грязным, и мне он не очень нравится. Какие у меня есть альтернативы? Возможно, я полностью неправильно использую наследование или совершенно неверно подхожу к нему. Я открыт для любых предложений и хотел бы использовать методы объектно-ориентированного проектирования для создания более чистых, разделенных проектов. Я действительно хотел бы знать, как люди решали подобные проблемы, и мы будем очень признательны за любые ресурсы, на которые вы можете направить меня.

Спасибо

6
задан filip-fku 20 August 2011 в 04:51
поделиться