Есть ли решение, позволяющее реализовать уровень абстракции с использованием дженериков для нескольких похожих типов с разными интерфейсами?

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

Рассмотрим типы IceCream. Все типы IceCream реализуют общий интерфейс, который требует наличия метода getFlavor(). Однако каждый тип IceCream также предоставляет несколько других методов. Типы IceCream включают такие вещи, как Gelato, WaterIce, FrozenCustard, ChilledCream и традиционный.

Некоторые типы IceCream предоставляют метод для получения производителя, но другие типы IceCream не имеют производителя и, следовательно, не предоставляют метод для получения производителя.

Кроме того, типы IceCream по-разному раскрывают метод getManufacturer() — одни называют его getManufacturer(), а другие — getMaker(), getChef() или getOwner(). Кроме того, один тип IceCream может иметь несколько отдельных методов, каждый из которых возвращает одних и тех же (или разных) производителей.

Учитывая некоторый набор типов IceCream, некоторые из которых имеют методы, возвращающие производителя (производитель всегда будет одним и тем же типом данных), как можно абстрагироваться от этих типов IceCream, чтобы они могли написать общую логику для работы с типами IceCream вместо дублирования всех кода, который используется для получения производителя для каждого типа IceCream отдельно?

К сожалению, эти классы не могут быть изменены.

Похоже, что для этого потребуется какое-то перечисление, содержащее отображение из Type -> String, а строки используются для рефлексивного разрешения методов класса. Есть ли другой общий способ реализовать это?


person user3015990    schedule 24.03.2015    source источник
comment
Я предлагаю вам использовать шаблон декоратора. Для каждого вида мороженого необходимо создать IceCreamDecorator. Декоратор реализует два интерфейса: IIceCream и IIceCreamManufactor, и вы передаете мороженое как внутренний класс. IIceCreamManufactor имеет один метод getManufactor, поэтому он будет инкапсулировать getMaker(), getChef() или getOwner() внутреннего класса. Таким образом, вы не меняете существующий код и можете расширять декоратор по своему усмотрению.   -  person Larry    schedule 24.03.2015
comment
если вам это нравится ... могу ли я создать новый ответ с ним, и вы отметите его как ответ?: P Просто хочу получить несколько баллов !!   -  person Larry    schedule 25.03.2015
comment
Конечно! Я думаю, что это достойный ответ - использовать декоратор для содержания сломанной абстракции.   -  person user3015990    schedule 25.03.2015


Ответы (3)


Я предлагаю вам использовать шаблон декоратора. Для каждого вида мороженого необходимо создать файл IceCreamDecorator. Декоратор реализует два интерфейса: IIceCream и IIceCreamManufactor, и вы передаете icecream как внутренний класс. У IIceCreamManufactor есть один метод, который называется getManufactor, поэтому он будет инкапсулировать getMaker(), getChef() или getOwner() внутреннего класса. Таким образом, вы не меняете существующий код и можете расширять декоратор по своему усмотрению.

person Larry    schedule 25.03.2015

Если бы вы могли изменить существующие типы IceCream, вы могли бы ввести новый интерфейс.

Поскольку это невозможно, следующим лучшим вариантом будет специальный класс для каждого из «полей»; как класс ManufactorerRetriever. В этом примере этот класс знает разные типы IceCream и как получить фактического производителя для разных типов. Это позволяет вам, по крайней мере, содержать все эти уродливые вызовы instanceof в центральном месте.

person GhostCat    schedule 24.03.2015
comment
Что, если нам нужно сделать еще одну неуниверсальную вещь с IceCream на основе его производителя? Мы просто создаем дополнительные сквозные классы абстракции поверх какого-то компонента функциональности IceCream? - person user3015990; 24.03.2015

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

person Laszlo Lugosi    schedule 24.03.2015
comment
Невозможно изменить существующие типы. - person user3015990; 25.03.2015