Вам слід використовувати інтерфейс (не успадкування) або якийсь механізм властивості властивостей (можливо, навіть те, що працює як рамки опису ресурсів).
Так чи
interface Colored {
Color getColor();
}
class ColoredBook extends Book implements Colored {
...
}
або
class PropertiesHolder {
<T> extends Property<?>> Optional<T> getProperty( Class<T> propertyClass ) { ... }
<V, T extends Property<V>> Optional<V> getPropertyValue( Class<T> propertyClass ) { ... }
}
interface Property<T> {
String getName();
T getValue();
}
class ColorProperty implements Property<Color> {
public Color getValue() { ... }
public String getName() { return "color"; }
}
class Book extends PropertiesHolder {
}
Пояснення (редагування):
Просто додайте необов'язкові поля в клас сутності
Особливо з додатковою обгорткою (редагуйте: див. Відповідь 4castle ). Я думаю, що це (додавання полів у оригінальну сутність) є життєздатним способом додавання нових властивостей у невеликому масштабі. Найбільшою проблемою такого підходу є те, що він може працювати проти низької зчеплення.
Уявіть, що ваш клас книг визначений у спеціальному проекті для вашої доменної моделі. Тепер ви додаєте ще один проект, який використовує модель домену для виконання спеціального завдання. Це завдання вимагає додаткової властивості в класі книги. Або ви закінчите спадщину (див. Нижче), або вам доведеться змінити загальну модель домену, щоб зробити нове завдання можливим. В останньому випадку ви можете закінчити купу проектів, які залежать від їх власних властивостей, доданих до класу книг, тоді як сам клас книги певним чином залежить від цих проектів, оскільки ви не в змозі зрозуміти клас книги без додаткові проекти.
Чому успадкування проблематично, коли мова йде про спосіб надання додаткових властивостей?
Коли я бачу ваш клас прикладу "Книга", я замислююся про об'єкт домену, який часто виникає з багатьма необов'язковими полями і підтипами. Уявіть собі, що ви хочете додати властивість для книг, які містять компакт-диск. Зараз існує чотири види книг: книги, книги з кольором, книги з компакт-дисками, книги з кольором та компакт-диск. Ви не можете описати цю ситуацію при спадкуванні на Java.
За допомогою інтерфейсів ви обходите це питання. Ви можете легко скласти властивості певного класу книг за допомогою інтерфейсів. Делегація та склад дозволять легко отримати саме той клас, який ви бажаєте. З успадкуванням у вас зазвичай виникають деякі необов'язкові властивості в класі, які існують лише тому, що їх потрібен клас.
Далі читайте, чому спадкування часто є проблематичною ідеєю:
Чому прихильники ООП взагалі сприймають спадщину як погану річ
JavaWorld: Чому поширюється - це зло
Проблема з реалізацією набору інтерфейсів для складання набору властивостей
Якщо ви використовуєте інтерфейси для розширення, все добре, якщо у вас є лише невеликий набір з них. Особливо, коли ваша об'єктна модель використовується та розширюється іншими розробниками, наприклад, у вашій компанії кількість інтерфейсів зростатиме. І врешті-решт ви створюєте новий офіційний "інтерфейс властивостей", який додає метод, який ваші колеги вже використовували у своєму проекті для клієнта X для абсолютно незв'язаного випадку використання - Ugh.
редагувати: Ще один важливий аспект згадується gnasher729 . Вам часто хочеться динамічно додавати необов'язкові властивості до вже наявного об'єкта. За допомогою успадкування або інтерфейсів вам доведеться відтворити весь об'єкт за допомогою іншого класу, який далеко не є обов'язковим.
Якщо ви очікуєте розширення до вашої об'єктної моделі до такої міри, вам буде краще, чітко моделюючи можливість динамічного розширення. Я пропоную щось подібне вище, де кожне "розширення" (в даному випадку властивість) має свій клас. Клас працює як простір імен та ідентифікатор для розширення. Якщо відповідно встановити конвенції про іменування пакету, цей спосіб дозволяє нескінченну кількість розширень, не забруднюючи простір імен для методів у вихідному класі сутності.
У процесі розвитку ігор ви часто стикаєтеся з ситуаціями, коли ви хочете складати поведінку та дані у багатьох варіантах. Ось чому структура -компонентна система архітектури отримала досить велику популярність у колах розвитку ігор. Це також цікавий підхід, який ви хочете переглянути, коли очікуєте багато розширень вашої об'єктної моделі.