Хорошо ли иметь класс, производный от базового класса и содержащий его экземпляр?
Я разрабатываю приложение, основанное на производителе/потребителе, и я застрял на представлении задачи, произведенной производителем в представлении класса.
Фактическая проблема выглядит так: производитель может произвестиStandaloneTask
, который может быть непосредственно потребляемым потребителем, или он может произвести CompressTask
, который должен пройти через TaskDecompressor
, которые извлекают его сначала в ряд StandaloneTask
, которые могут быть потреблены потребителями.
Поскольку существует много общего между StandaloneTask
и CompressTask
, поэтому я создал базовый класс под названием TaskBase
, который содержит всю эту общую информацию.
class abstract TaskBase
{
}
class StandloneTaskType1: TaskBase
{
}
class StandloneTaskType2: TaskBase
{
}
.
.
.
class StandloneTaskTypeN: TaskBase
{
}
Как работает распаковка задачи?
Задача может иметь один или несколько параметров, которые необходимо заполнить во время выполнения. Задача сжатия состоит из задачи с параметрами и другой информацией о том, как получить значения, которые необходимо заполнить в этих параметрах. После получения значений предполагается, что A TaskDecompressor
заполняет все эти значения в параметризованной задаче для создания одного или нескольких автономных задача.
Я создал класс CompressTask
следующим образом.
class CompressTask: TaskBase
{
TaskBase task;
//runtime parameters
}
Теперь мне кажется очень странным, что CompressTask
является производным от TaskBase
, а также содержит экземпляр TaskBase
. Правильно ли иметь такой класс? Или есть ли лучшее классовое представление данного случая.
4 ответа:
В целом эта структура не является редкостью, вы несколько начинаете идти по путикомпозитного паттерна . Ваш
Я бы рекомендовал прочитать об этом шаблоне проектирования и потенциально подумать о том, чтобы облегчить потребителю использование любого подкласса TaskBase независимо от того, является ли онCompressTask
отчасти действует как композит, а вашStandaloneTask
- Как лист.CompressTask
илиStandaloneTask
. Это укрепит ваш дизайн и упростит потребление.
Представьте...
class Student: Person { Person father; Person mother; Date dateOfEnrollment; }
В этом есть смысл, не так ли? В принципе, в вашем классе Compressstask нет ничего плохого.
Одно важное правило проектирования ОО: предпочтение композиции над наследованием реализации. Просто потому, что
Возвращаясь к вашему случаю,StandaloneTask
иCompressTask
имеют много общих черт, это не делает их хорошим выбором, чтобы позволить им использовать один и тот же базовый класс. Если два класса разделяют некоторые интерфейсы, рекомендуется разложить интерфейсы на множители с помощьюнаследования интерфейса . Если два класса совместно используют некоторые реализации, вам лучше разложить реализацию на некоторый класс и внедрить его в указанный класс. два класса (т. е. композиция ).CompressTask
является производным отTaskBase
и также содержит экземпляр TaskBase. Это означает, что вы используете наследование реализации и композицию одновременно, что не очень хорошо пахнет. Следующий скелет как раз для вашей справки:interface Task { // some common Task interface here... } class TaskImpl // Or: class TaskImpl : Task // depends on your needs { // some common Task-related implementation here... } class CompressTask: Task // interface inheritance, NOT implementation inheritance { TaskImpl taskImpl; // contains *reusable* task-related implementation Task task; // contains the target task(s) to be compressed // other code... } class StandloneTaskType1: Task { TaskImpl taskImpl; // other code... } . . . class StandloneTaskTypeN: Task { TaskImpl taskImpl; // other code... }
Еще лучше... Воображать...
class Foo // implicitly extends Object { String name; // also a direct subclass of Object (at least in Java anyway) Integer age; // extends Number, which extends Object (at least in Javaland) Object theRootOfAllEvil; // a raw instance of the superclass int i; // the only member that is not an Object }
Пожалуйста, простите мой Яванский, но там, откуда я родом, нет ничего плохого во всем этом;)
Все зависит от мелочей ваших занятий.