Нужна помощь по шаблону стратегии

Существует interface Algorithm

Существует class MathAlgorythm implements Algorithm (returns MathResult, which implements Result)

Существует class ChemitryAlgorythm implements Algorithm (returns ChemitryResult, which implements Result)

Кроме того, существует Context class, который используется для передачи данных этим алгоритмам. Данные передаются следующим образом:

public Result executeStrategy(Data data) {
    return algo.execute(data);
}

Предположим, я выполнюStrategy и вернусь return MathAlgorithm.execute(data); Я получаю что-то типа Result, верно?

Затем я выполняю return ChemitryAlgorithm.execute(data); снова, я получаю что-то. Результат

Вопрос: Результатом является интерфейс. Мне нужно получить доступ к конкретной реализации класса как MathResult или ChemistryResult. Другими словами. Как только я получаю что-то типа Result, мне нужно копнуть глубже и узнать, какой класс скрывается за интерфейсом.

Надеюсь, эта бессвязность не слишком сбивает с толку.

Спасибо, что прочитали и ответили


person James Raitsev    schedule 29.12.2010    source источник
comment
Кстати, это algorithm с i.   -  person BalusC    schedule 30.12.2010
comment
Стратегия обычно используется, когда разные алгоритмы используются для получения (по существу) одного и того же результата. Таким образом, лучшим примером может быть оптимизатор, чьи различные стратегии являются крутыми спусками или сопряженными градиентами. Трудно рассматривать математику и химию как альтернативные стратегии. (В результате можно было бы использовать поле для класса стратегии, если это все, что требуется)   -  person peter.murray.rust    schedule 30.12.2010
comment
Ты прав. Задача именно в этом — сгруппировать разные Результаты под одним зонтиком. Если бы и Math..., и Chemistry... возвращали один и тот же объект, проблем бы не было. сейчас поищу оптимизатор   -  person James Raitsev    schedule 30.12.2010


Ответы (4)


Если вы дадите Result такой метод, как T get(), который должны реализовать конкретные реализации, вам не нужно знать о конкретных реализациях.

person BalusC    schedule 29.12.2010

Не уверен, понял ли я ваш вопрос, но чтобы узнать конкретный класс экземпляра, вы можете использовать getClass() или, альтернативно, использовать instanceof, чтобы проверить, является ли он MathResult и т. д. Будьте осторожны, чтобы не победить весь смысл реализации интерфейса Result.

person jbx    schedule 29.12.2010

Убедитесь, что ваш интерфейс результатов достаточно надежен, чтобы удовлетворить всех клиентов. Это ключ к тому, чтобы не нарушать полиморфную прозрачность.

Если вам действительно, действительно, ДЕЙСТВИТЕЛЬНО нужно знать конкретный тип, вы можете либо использовать getClass, какой-то уникальный идентификатор и геттер, либо (наиболее предпочтительно) поглотить поведение в операцию конкретного класса Result.

person Mike    schedule 30.12.2010

Как насчет:

interface Algorithm<R extends Result, D extends Data> {
  T execute data(D data);
}

и тогда ваша реализация MathAlgorithm будет выглядеть так:

class MathAlgorithm implements Algorithm<MathResult, MathData> {
  public MathResult execute(MathData data) {
    // do whatever
    return <instance of MathResult>;
  }
}

Использование:

MathResult mathResult = new MathAlgorithm().execute(someMathData);
person ytoh    schedule 30.12.2010
comment
Да спасибо. Проблема в том, что при получении результата я не хочу получать MathResult или ChemistryResult. Мне просто нужен результат, если это возможно. Как только я его получу, я хотел бы посмотреть, что это за результат, и пойти оттуда. - person James Raitsev; 30.12.2010