У меня есть концептуальная проблема с правильной реализацией кода, которая, по-видимому, требует множественного наследования, что не было бы проблемой во многих языках ОО, но поскольку проект для Android, такого понятия, как множественное, не существует extends
.
У меня есть куча деятельности, полученная от различных базовых классов, таких как простой Activity
, TabActivity
, ListActivity
, ExpandableListActivity
и т.д. Кроме того, у меня есть некоторые фрагменты кода , которые мне нужно место в onStart
, onStop
, onSaveInstanceState
, onRestoreInstanceState
и другие стандартные обработчик событий во всех видах деятельности.
Если бы у меня был один базовый класс для всех действий, я бы поместил код в специальный промежуточный производный класс, а затем создал бы все действия, расширяющие его. К сожалению, это не так, потому что есть несколько базовых классов. Но размещение одних и тех же частей кода в нескольких промежуточных классах - не лучший способ, имхо.
Другой подход может состоять в том, чтобы создать вспомогательный объект и делегировать все вызовы вышеупомянутых событий помощнику. Но это требует включения вспомогательного объекта и переопределения всех обработчиков во всех промежуточных классах. Таким образом, здесь нет большой разницы с первым подходом - все еще много дубликатов кода.
Если бы подобная ситуация произошла в Windows, я бы создал подкласс базового класса (что-то, что «соответствует» Activity
классу в Android) и перехватывал там соответствующие сообщения (в одном месте).
Что для этого можно сделать в Java / Android? Я знаю, что есть интересные инструменты, такие как инструментарий Java ( с некоторыми реальными примерами ), но я не гуру Java и не уверен, стоит ли пытаться в этом конкретном случае.
Если я пропустил некоторые другие достойные решения, пожалуйста, упомяните их.
ОБНОВИТЬ:
Для тех, кто может быть заинтересован в решении той же проблемы в Android, я нашел простой обходной путь. Существует класс Application , который предоставляет, помимо прочего, интерфейс ActivityLifecycleCallbacks . Это делает именно то, что мне нужно, позволяя нам перехватывать и добавлять некоторую ценность в важные события для всех видов деятельности. Единственным недостатком этого метода является то, что он доступен начиная с уровня API 14, чего во многих случаях недостаточно (поддержка API уровня 10 является типичным требованием сегодня).
decordator pattern
. Это последнее средство, которое хотя на самом деле демонстрирует то, что я бы предпочел избежать - дублирование кода. Я приму ваш ответ, если нет других интересных идей. Могу ли я использовать дженерики для обобщения кода «промежуточных звеньев»?Я думаю, что вы пытаетесь избежать неправильного типа дублирования кода. Я верю, что Майкл Фезерс написал статью об этом, но, к сожалению, я не могу ее найти. Как он описывает это, вы можете думать о своем коде как о двух частях, похожих на оранжевый: кожура и мякоть. Оболочка - это такие вещи, как объявления методов, объявления полей, объявления классов и т. Д. Целлюлоза - это вещи внутри этих методов; реализация.
Когда дело доходит до СУХОГО, вы хотите избежать дублирования мякоти . Но часто в процессе вы создаете больше кожуры. И это нормально.
Вот пример:
Это может быть преобразовано в это:
Мы добавили много кожуры в этот рефакторинг. Но, во втором примере намного чище
method()
с меньшими нарушениями.Вы сказали, что хотите избежать шаблона декоратора, потому что это приводит к дублированию кода. Если вы посмотрите на изображение в этой ссылке, то увидите, что оно будет только дублировать
operation()
подпись (например, rind).operation()
Реализации (пульпы) должны быть различными для каждого класса. Я думаю, что ваш код в результате станет чище и будет иметь меньшее дублирование.источник
Вы должны предпочесть композицию наследству. Хорошим примером является « шаблон » IExtension в среде .NET WCF. По сути, у вас есть 3 интерфейса, IExtension, IExtensibleObject и IExtensionCollection. Затем вы можете составить различные варианты поведения с помощью объекта IExtensibleObject, добавив экземпляры IExtension в его свойство Extension IExtensionCollection. В Java это должно выглядеть примерно так, однако вам не нужно создавать собственную реализацию IExtensioncollection, которая вызывает методы присоединения и отсоединения при добавлении / удалении элементов. Также обратите внимание, что вам нужно определить точки расширения в вашем расширяемом классе. В примере используется механизм обратного вызова, похожий на событие:
Этот подход имеет преимущество повторного использования расширений, если вам удается извлечь общие точки расширения между вашими классами.
источник
processor.addHandler(console)
при условии, чтоConsoleProcessor
будет реализовывать сам интерфейс обратного вызова. Шаблон "extension" выглядит как миксинvisitor
иdecorator
, но так ли это необходимо в этом случае?Начиная с Android 3.0, это может быть элегантно решить с помощью фрагмента . Фрагменты имеют свои собственные обратные вызовы жизненного цикла и могут быть размещены внутри Действия. Я не уверен, что это будет работать для всех событий, хотя.
Другой вариант, в котором я также не уверен (не имея глубоких ноу-хау в Android), может заключаться в том, чтобы использовать Decorator противоположным способом, который предлагает k3b: создайте
ActivityWrapper
методы обратного вызова, содержащие ваш общий код, и затем перенаправьте на обернутыйActivity
объект (ваш фактические классы реализации), а затем Android запустить эту оболочку.источник
Это правда, что Java не допускает множественного наследования, но вы можете более или менее смоделировать его, сделав каждый из ваших подклассов SomeActivity расширением исходного класса Activity.
У вас будет что-то вроде:
источник