ООП-Дизайн: методы интерфейса с параметрами, зависящими от реализации - PullRequest
5 голосов
/ 02 февраля 2012

Субъект говорит это уже:

Я сейчас думаю о следующей проблеме дизайна: я определяю интерфейс для конкретного типа объекта, который содержит различные методы.Теперь у меня есть проблема, что различным реализациям этого интерфейса требуются дополнительные / разные методы-параметры (потому что способ их реализации делает это необходимым), который я не могу включить в интерфейс, потому что они не являются общими для all реализации интерфейса.

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

В настоящее время я могу думать только о том, чтобы передать Map<String, Object> parameters для преодоления этой проблемы - поскольку JDK-классы, такие как DocumentBuilderFactory , делают нечто очень похожее, предоставляя такие методы, как setAttribute(String attName, Object attValue), это выглядит как выполнимый подходДля решения этой проблемы.Тем не менее, мне было бы интересно узнать, как другие решают подобные проблемы, альтернативные идеи?

Я не хочу выводить из интерфейса и добавлять дополнительные методы, поскольку в моем случае мне бы пришлось выбросить NotImplementException изметоды базового интерфейса.

ОБНОВЛЕНИЕ :

Какие могут быть возможные проблемы Map-подхода?Реализующие классы могут полностью игнорировать его, если они не могут использовать дополнительные параметры.Другие могут проверить, содержит ли Map требуемые имена параметров, проверить тип их значений и использовать их, если они действительны, если нет, выдать исключение.Я также видел, как это используется для абстрактного класса JAXBContext, так что, похоже, это общий подход ..

ОБНОВЛЕНИЕ :

Я решил пойти на карту- Подход, так как я не вижу никаких явных недостатков, и он также используется в JDK (да, я знаю, что это не обязательно много значит :) Поскольку я не могу принять ответ на этот вопрос, я просто буду голосовать.Спасибо за ваш вклад!

С уважением,

- qu

Ответы [ 6 ]

1 голос
/ 02 февраля 2012

Вы должны просто инициализировать каждого наследника с его собственными определенными обязательными параметрами и оставить метод интерфейса без параметров, как в:

Интерфейс Runnable:

public interface Runnable {
    public abstract void run();
}

Реализация:

public class MyRunnable {

    private final String myConcreteString;

    public MyRunnable(String myConcreteString) {
        this.myConcreteString = myConcreteString;
    }

    public void run() {
        // do something with myConcreteString
    }
}
1 голос
/ 02 февраля 2012

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

Если вам абсолютно необходимо это сделать, есть достаточно простой способ, который я использовал раньше.Я просто не очень хорошо говорю на других языках.Я уверен, что есть способы реализовать это и в Java.

SomeMethod(void* parameterData);

void* parameterData - это указатель на структуру, содержащую ваши данные.В каждой реализации вы знаете, что вы получаете.Вы даже можете иметь перечисление, чтобы сообщить вам, какие данные вы получаете.

SSomeData* data = (SSomeData)parameterData

РЕДАКТИРОВАТЬ:

Еще один подход заключается в создании нового интерфейса дляпараметры: IParameterData.
Внутри этого интерфейса у вас есть 2 метода: GetParameter(name) и SetParameter(name).
Для каждой реализации вашего основного интерфейса вы создаете реализацию IParameterData.

* 1025.* Надеюсь, это поможет
1 голос
/ 02 февраля 2012

не могли бы вы спроектировать подынтерфейсы, которые расширяют ваш (супер) интерфейс? Во всяком случае, я вижу проблему дизайна, если вам нужен метод с различными параметрами в зависимости от реализации!

изменить: код для уточнения

interface CommonBehaviour
{
    void methodA(int aParam);
}

interface SpecificBehaviour extends CommonBehaviour
{
    void methodB(int aParam, int anotherParam);
}

class SpecificBehaviourImpl implements SpecificBehaviour 
{
   void methodA(int aParam)
   {
      //do something common
   }

   void methodB(int aParam, int anotherParam)
   {
      //do something specific
   }
}

CommonBehaviour myObj = new SpecificBehaviourImpl();

РЕДАКТИРОВАТЬ: Вы можете извлечь выгоду из шаблона команды: «Использование объектов команд упрощает создание общих компонентов, которые должны делегировать, упорядочивать или выполнять вызовы методов во время их выбора без необходимости знать владельца метода или параметров метода». (источник: Википедия)

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

0 голосов
/ 02 февраля 2012

На вашем месте, я бы рассмотрел поиск подходящего шаблона проектирования для вашей проблемы, а не пытался бы изменить методы интерфейса в соответствии с вашими потребностями. Изучите шаблон стратегии для начала.

0 голосов
/ 02 февраля 2012

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

0 голосов
/ 02 февраля 2012

Можете ли вы обратить проблему и реализовать интерфейс пользователя этих объектов, который он может запросить для дополнительных параметров?

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

Скажем, в вашем интерфейсе есть метод doSomething, принимающий параметр "a", но у вас есть реализация, которая должназнать, что «b» находится внутри этого метода «doSomething».Для получения этой информации он вызвал бы getB для объекта, который вы предоставили его конструктору.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...