5

I'm currently working on a project where we have to represent a set of vectors in a 3D environment. We have several different visualization implementations.

I came to the idea, that I could bundle all the visualization types in an enum. I have defined an Interface VectorVisualization and several implementations which implement this interface.

Now I have added to the Interface class the following enum:

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);
}

The label is for a JComboBox in the Gui. So I can now just iterate over the enum and get the label of the different types. Also to set a Implementation I can use the enum like that:

VectorVisualizationType.CYLINDER.getVisualization()

But is this a nice way? Or are there any problems with that approach? Of course, now when you've created a new implementation you have to add this to the enum.

Thanks for your opinion!

Prine
  • 12,192
  • 8
  • 40
  • 59

2 Answers2

1

Interesting. I've used enumerated types to carry around useful bits of metadata before, but never taken it quite so far as storing pieces of executable code.

That said, the only issue I see with your approach is that, as you have already noted, when you create a new VectorVisualization implementation you will have to manually add a new entry to the enumeration. Generally I prefer to avoid such manual overhead where possible, but really that's a matter of personal preference.

If you (and everyone else working on this code with you) are aware of this constraint and don't mind it, then I think your solution is fine.

Do note that your current structure requires every VectorVisualization to be implemented in a thread-safe manner, because there is only a single instance that is handed out to everyone who references it through the enumerated type. If this is an issue you could work around it by storing the implementation classes against the enumeration instead of implementation instances, and then simply modify getVisualization() to create a new instance of the associated implementation class when it is called. This would place an additional restriction against VectorVisualization implementations, that each one needs to provide a public 0-parameter constructor which creates a usable instance of the implementation.

aroth
  • 54,026
  • 20
  • 135
  • 176
  • Thanks for your answer! That's a good point with the Thread-Safety. But in our case it shouldn't be a problem. Another way to provide similar functionality would be using a map where you would use the enum as a key and the VectorVisualization as a value. But when adding a new implementation you have to define that at two code locations instead of one with the enum.. So I'm still on the enum side :). – Prine Aug 06 '11 at 13:00
  • @Prine - Yes, I've used the map-based approach numerous times in the past, but it provides no benefit over what you have done with the enum (possible exception: you can add new entries to the map dynamically at runtime, and/or remove existing ones), so I didn't bring it up. The next time I need it, I may try your enum-based idea instead. – aroth Aug 06 '11 at 13:03
1

Using an enumeration to list the current implementations have a number of very nice properties. E.g. it is pretty easy to find all current implementations as they by definition must be listed in the enumeration declaration and you have the standard enum interface to get access to the implementations.

But it also makes it impossible to extend the current set in a pluggable way - so a 3rd party cannot add a new implementation. For this very reason I usually like to use a singleton manager that will hold all implementations. This pattern also plays very nicely with many component frameworks like OSGi.

Tonny Madsen
  • 12,628
  • 4
  • 31
  • 70