2015-05-22 3 views
-2

У меня есть интерфейс и его реализации:Добавление новых реализаций безопасно

public interface SyntaxConstruction{ 
    public String parseFromString(String str); 
} 
public class Copy implements SyntaxConstruction{ 
    public String parseFromString(String str){ //impl }; 
} 


public class Set implements SyntaxConstruction{ 
    public String parseFromString(String str){ //impl }; 
} 

У меня также есть следующий класс:

public class Parser{ 

    private static List<SyntaxElement> elementPrototypes; //should maintain the list of all implementation's prototypes 


    static{ 
     //Initializing list with prtotypes of all possible SyntaxConstruction's implementations 
    } 
    public static List<SyntaxElement> parse(String str){ 
     //getting syntax elements from str 
    } 
} 

Теперь мы добавим новую реализацию, скажем

public class Values implements SyntaxConstruction{ 
    public String parseFromString(String str){ //impl }; 
} 

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

+0

Что он должен там обновить? 'elementPrototypes' даже не инициализирован, поэтому мы не знаем, что он содержит :(Если он должен содержать каждую реализацию, то не позволяйте кому-то« заполнять »его и делать это самостоятельно, используя отражение: http: // stackoverflow.com/questions/347248/how-can-i-get-a-list-of-all-the-implementations-of-an-interface-programmatically – Tom

+0

@Tom Не могли бы вы посмотреть обновленный вопрос? – user3663882

+2

Написание новая реализация нарушает существующую функциональность? Пахнет как плохой дизайн. – fabian

ответ

2

Вы можете использовать абстрактную реализацию, «зарегистрировать» сам (в конструкторе) в Parser «s elementPrototypes, что-то вроде:

public abstract class BaseSyntaxConstruction implements SyntaxConstruction { 
    protected BaseSyntaxConstruction() { 
     Parser.addElementPrototype(this); 
    } 
} 

public class Copy extends BaseSyntaxConstruction { 
    public String parseFromString(String str){ 
     // impl 
    } 
} 

Обратите внимание, что вы можете также использовать отражение для„обнаружения“SyntaxConstruction реализаций


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

enum SyntaxConstruction { 
    COPY { 
     @Override 
     public String parseFromString(String str){ 
      // impl 
     } 
    }, 
    // ... 

    ; 

    public abstract String parseFromString(String str) 
} 
+0

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

+0

Вы можете удалить интерфейс и использовать абстрактный класс с абстрактным методом 'parseFromString' => no bypass –

+0

Итак, экземпляр будет adde только при попытке их создания? Может быть, я должен сказать, '' Parser.addElementPrototype (new Copy()); 'в статический инициализатор? – user3663882

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