Почему и когда использовать реализацию скелета в java

Из Effective Java Item 18, где он предлагает, мы можем объединить интерфейсы и абстрактные классы, предоставив абстрактный класс реализации скелета. Мне интересно, когда следует использовать скелетную реализацию для имитированного множественного наследования? и каковы преимущества и недостатки? Может ли кто-нибудь привести пример?

Ответ 1

Точка "Скелетного класса", как вы выразились, заключается в основном в соблюдении определенных основных правил, которые будут определять использование вашего дизайна. Сами по себе интерфейсы и абстрактные классы не могут выполнять эту работу. Рассмотрим интерфейс, например

  1. Вы не можете указать какие-либо сведения о реализации своих методов
  2. переменные, указанные на уровне интерфейса, должны быть статическими.
  3. Интерфейсы ничего не могут реализовать (класс или интерфейс)

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

Теперь возьмем абстрактный класс

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

Сочетание обоих дает вам лучшее из обоих миров в этом

  1. Абстрактный класс может реализовать интерфейс. Класс реализации может расширить ваш абстрактный класс, чтобы получить преимущества уже реализованных методов интерфейса. И эта цепочка может продолжаться столько абстрактных классов, сколько необходимо, вплоть до конкретной реализации
  2. Класс реализации может реализовать столько интерфейсов, сколько необходимо для целей маркерного типа. Таким образом, вы можете иметь столько интерфейсов Serializable для маркировки, которые будут расширены другими интерфейсами
  3. Класс, реализующий абстрактный класс (который реализует интерфейс), может быть определен как тип интерфейса, чтобы извлечь выгоду из лучшего полиморфизма при создании в виде дочернего элемента абстрактного класса

Рассмотрим этот вариант использования

  • У вас есть интерфейс, который имеет около 6 методов, которые будут определять использование класса, тогда у вас есть интерфейс маркера, который вам нужен просто для целей идентификации, поэтому вы можете использовать, возможно, оператор instanceOf.
  • Теперь в этом первом интерфейсе вам необходимо выполнить определенную реализацию только из трех этих методов, а остальные 3 - для конечных пользователей этого класса.
  • Таким образом, интерфейс A имеет 6 определений методов, интерфейс B - это всего лишь маркер для класса, который говорит: "Я - класс типа B". Теперь у вас будет класс A, абстрактный класс, реализующий оба интерфейса A и B
  • В вашем абстрактном классе вы реализуете только нужные 3 метода. Затем вы оставляете детали реализации других 3 методов конечным потребителям этого абстрактного класса