Использование перечислений в качестве контейнера реализаций - PullRequest
5 голосов
/ 06 августа 2011

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

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

Теперь я добавил в класс Interface следующее перечисление:

public interface VectorVisualization {

    public enum VectorVisualizationType {
       CYLINDER(new VectorVisualizationCylinder(), "Cylinder"),
       CONES(new VectorVisualizationCones(), "Cones"),
       FATCONES(new VectorVisualizationFatCones(), "Fat cones"),
       ARROWS(new VectorVisualizationArrows(), "Arrows");

       private final String label;
       private final VectorVisualization vis;

       VectorVisualizationType(VectorVisualization vis, String label) {
           this.vis = vis;
           this.label = label;
       }

       public VectorVisualization getVisualization() {
           return this.vis;
       }

       public String getLabel() {
           return this.label;
       }
   }

   void prepareVBO(GL gl, ArrayList<VectorData> vectors, VectorField field);
   void render(GL gl);
   void clearOldVBOS(GL gl);
}

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

VectorVisualizationType.CYLINDER.getVisualization()

Но это хороший способ? Или есть какие-то проблемы с этим подходом? Конечно, теперь, когда вы создали новую реализацию, вы должны добавить это в перечисление.

Спасибо за ваше мнение!

Ответы [ 2 ]

1 голос
/ 06 августа 2011

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

Но это также делает невозможным расширение текущего набора подключаемым способом - так что третье лицо не может добавить новую реализацию. Именно по этой причине мне обычно нравится использовать одноэлементный менеджер, который будет содержать все реализации. Этот шаблон также очень хорошо работает со многими компонентами, такими как OSGi.

1 голос
/ 06 августа 2011

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

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

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

Обратите внимание, что ваша текущая структура требует, чтобы каждый VectorVisualization был реализован потокобезопасным способом, потому что существует только один экземпляр, который раздается всем, кто ссылается на него через перечислимый тип. Если это проблема, вы можете обойти ее, сохранив классы реализации вместо перечисления вместо экземпляров реализации, а затем просто измените getVisualization(), чтобы создать новый экземпляр связанного класса реализации при его вызове. Это наложит дополнительное ограничение на VectorVisualization реализаций, для каждой из которых необходимо предоставить открытый конструктор с 0 параметрами, который создает пригодный для использования экземпляр реализации.

...