2015-10-25 2 views
0

Я пытаюсь построить алгоритм, который работает по-разному в зависимости от стратегии обхода и стратегии обновления . Однако не каждая стратегия обновления работает с каждой стратегией обхода. Следовательно, я решил, что стратегия обновления должна быть создана только с соответствующей стратегией прохождения. Я хотел создать для этого конструктор (см. Ниже). Чтобы подклассы должны были проверить, поддерживают ли они эту стратегию.Java Связь между интерфейсами/абстрактными классами

я в настоящее время имеющий интерфейс

public interface TraversalStrategy { 
... 
} 

И в (недопустимый) абстрактный класс

public abstract class UpdateStrategy { 
protected TraversalStrategy travStrategy; 

public abstract UpdateStrategy(TraversalStrategy travStrategy); 
} 

Что такое правильный способ подразумевает такую ​​зависимость? Я мог бы, конечно, добавить к этому конструктору пустое тело, но это показалось мне неправильным.

Update: Вдохновленный Ответ @Kayaman, я создал новый класс TestcaseGenerator, который используется для построения правильного сочетания.

public TestcaseGenerator(TraversalStrategy travStrategy, UpdateStrategy updStrategy){ 
    if (updStrategy.supports(travStrategy)){ 
     this.travStrategy = travStrategy; 
     this.updStrategy = updStrategy; 
    } 
} 

Current Class Diagram

Что мне не нравится об этом еще есть, что теперь было бы излишним, чтобы дать экземпляр TraversalStrategy к UpdateStrategy, чтобы проверить, если она поддерживается. Я бы предпочел только имя класса. Можете ли вы рассказать мне, как достичь этого? Эксперименты с .getClass().getName() казались ужасными. В настоящее время я делаю:

public boolean supports(TraversalStrategy travStrategy){ 
    if(travStrategy instanceof UpstreamTraversalStrategy){ 
     return true; 
    } 
    return false; 
} 
+2

что вы думаете? – eliasah

+0

Известны ли все возможные стратегии обновления и обхода (и какие стратегии совместимы друг с другом)? –

+0

@PinkieSwirl На самом деле это синтаксическая ошибка. – Kayaman

ответ

1

Один из распространенных способов, чтобы иметь суперкласс вызова конструктора абстрактный метод такой, как isSupported(TraversalStrategy t); и потерпеть неудачу, если это не так.

Подклассы затем реализуют этот метод, используя instanceof или любым другим способом, чтобы определить, поддерживается ли стратегия.

Одним из подходов было бы создание третьего класса с использованием шаблона Builder. Вместо предоставления TraversalStrategy в качестве параметра UpdateStrategy они оба будут включены в третий объект (и их можно было бы проверить на build(), чтобы предотвратить несовместимые стратегии).

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

+2

Я как раз собирался ответить таким же образом, но потом я вспомнил, что Джошуа Блох сказал, что всегда неправильно вызывать переопределяемый метод из конструктора. http://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-constructors –

+0

Хм, справа. Давайте посмотрим ... – Kayaman

+0

Спасибо, это звучит как действительная идея. Я собираюсь экспериментировать и давать отзывы завтра :). – Koronis

1

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

+0

Вот как я его реализовал. Но я чувствую, что это заставляет людей думать, что уже есть какая-то проверка в суперварианте (TraversalStrategy travStrategy). И это неправда. Я хочу, чтобы будущие программисты понимали, что они имеют отношение к конструктору. Или найти лучшее решение. :) – Koronis

+0

Итак, поставьте его как контракт в JavaDoc конструктора. Это будет документировать API, который будет наиболее важен для любого будущего разработчика, использующего этот абстрактный класс. – hotzst

Смежные вопросы