Должен ли я использовать абстрактный или интерфейс... или начать с конкретного класса, который должен быть расширен?

Мне не хватает контроля над ОО-дизайном, чтобы определить, хорошо ли я проектирую приложение или нет.

Вот простая идея:

Я хочу написать заявку на поездку в метро.

Я начал определять следующее:

Trainline Интерфейс, который определяет некоторые методы. Затем я создаю конкретный класс под названием Lines. Класс Lines ничего не делает вообще. У него есть методы, такие как getNumberOfStations(), но он не знает ни о каком количестве станций, поэтому просто возвращает ноль.

Затем у меня есть класс CentralLine, который выполняет реальную работу, и это расширяет линии, и это обеспечивает реальную реализацию.

Вопросы:

  1. Нужен ли конкретный класс "Линии"? Должен ли я просто не использовать CentralLine и CircleLine для реализации TrainLines (это обе линии поезда в лондонском метро)?
  2. Или я должен удалить интерфейс TrainLines и просто иметь конкретный класс Lines?
  3. Или TrainLines должен быть абстрактным классом?
  4. Предоставляет ли интерфейс или суперкласс Lines какое-либо значение, кроме симпатичной диаграммы карты классов... см. Выше:)
  5. Что OO может сделать для меня, что было бы здорово? Что я должен искать в ОО-дизайне?

Спасибо!!!!

3 ответа

Исходя из того, что вы уже показали, у вас должен быть только один класс: Line учебный класс.

Пара причин (для ответа 1-4):

Вы должны использовать наследование экономно. Трудно кратко объяснить, почему это наследование, особенно в Java (где у нас нет признаков или многократного наследования, а изменчивость широко распространена), как правило, не очень хороший дизайн. Вы можете Google Gang of four composition over inheritance,

Занятия не должны быть конкретными вещами. То есть вы бы не сделали класс с вашим именем производным от Human, Классы - это категория вещей.

Если вам нужно больше типов LineВы просто рефакторинг. Особенно в Java, где рефакторинг очень прост. Я думаю, что они фундаментально преподают разработку программного обеспечения / дизайн неправильно из того, что происходит в реальном мире. В реальном мире вы не знаете всей области (или таксономии), поэтому вы всегда начинаете с самой простой модели, а затем выполняете рефакторинг.

Чтобы ответить на вопрос № 5:

Что OO может сделать для меня, что было бы здорово? Что я должен искать в ОО-дизайне?

Если вы не знаете о модульном тестировании, вы должны изучить это (хороший дизайн ничего не значит, если вы не можете его протестировать... на самом деле, если вы не можете протестировать свой код или его сложно протестировать = плохой дизайн).

С ООП вы должны решить, как вы хотите управлять состоянием. ООП очень хорошо справляется с управлением в памяти. Его лучшим преимуществом является моделирование чего-то вроде видеоигры или пользовательского интерфейса, где у вас много состояния памяти.

Почему бы не сделать свой Lines учебный класс abstract? у вас не было бы проблемы "возврата нуля" => очень и очень уродливо.

В этом случае вы бы не имели TrainLines интерфейс больше.

TrainLinesИнтерфейс был бы интересен, если вы планируете иметь дело со многими Lines чья реализация действительно отличается. Таким образом, вы бы выиграли с большим полиморфизмом, ссылаясь на различные классы в вашем коде с помощью TrainLines тип.

Подводя итог, оба решения:

  • Lines за абстрактным классом следуют конкретные классы.
  • TrainLines как интерфейс следует Lines (или другие типы) как абстрактный класс следует за конкретными классами.

Имейте в виду, что абстрактный класс, реализующий интерфейс, не должен реализовывать методы. Действительно, абстрактный класс может отложить эту ответственность до конкретного класса. Таким образом, нет необходимости внедрять манекен return null;)

Я не вижу никакой реальной потребности в интерфейсе в вашем случае. Я бы сделал Lines абстрактным классом и предоставил бы все общие реализации в классе Lines. CentralLine и CircleLine могут использовать эту реализацию по умолчанию и предоставлять реализацию для остальных методов.

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

Интерфейсы могут быть очень полезны, когда вы хотите иметь реализацию в разных иерархиях, также, поскольку один и тот же класс может реализовывать несколько интерфейсов, это может быть полезно. Но в интерфейсе всегда есть предостережение, что если нужно добавить новый метод, тогда вся иерархия может сломаться, тогда как в случае абстрактного класса вы можете просто поместить реализацию по умолчанию в абстрактный класс, не изменяя ничего другого.

Другие вопросы по тегам