【问题标题】:Using enums as a container of implementations使用枚举作为实现的容器
【发布时间】:2011-10-21 11:07:21
【问题描述】:

我目前正在进行一个项目,我们必须在 3D 环境中表示一组矢量。我们有几种不同的可视化实现。

我想到了可以将所有可视化类型捆绑在一个枚举中。我已经定义了一个接口 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);
}

标签用于 Gui 中的 JComboBox。所以我现在可以遍历枚举并获取不同类型的标签。另外要设置一个实现,我可以像这样使用枚举:

VectorVisualizationType.CYLINDER.getVisualization()

但这是个好方法吗?或者这种方法有什么问题吗?当然,现在当你创建了一个新的实现后,你必须将它添加到枚举中。

感谢您的意见!

【问题讨论】:

    标签: java oop design-patterns enums strategy-pattern


    【解决方案1】:

    有趣。我以前使用枚举类型来携带有用的元数据位,但从未将其用于存储可执行代码片段。

    也就是说,我在您的方法中看到的唯一问题是,正如您已经指出的那样,当您创建一个新的 VectorVisualization 实现时,您必须手动向枚举添加一个新条目。一般来说,我宁愿尽可能避免这种手动开销,但这实际上是个人喜好问题。

    如果您(以及与您一起处理此代码的其他所有人)都知道此限制并且不介意,那么我认为您的解决方案很好。

    请注意,您当前的结构要求每个VectorVisualization 都以线程安全的方式实现,因为只有一个实例会分发给通过枚举类型引用它的每个人。如果这是一个问题,您可以通过针对枚举而不是实现实例存储实现类来解决它,然后只需修改getVisualization() 以在调用时创建关联实现类的新实例。这将对VectorVisualization 实现施加额外的限制,即每个实现都需要提供一个公共的 0 参数构造函数,该构造函数创建一个可用的实现实例。

    【讨论】:

    • 感谢您的回答!这是线程安全的一个好点。但在我们的情况下,这应该不是问题。提供类似功能的另一种方法是使用地图,您可以在其中使用枚举作为键,将 VectorVisualization 作为值。但是当添加一个新的实现时,你必须在两个代码位置定义它,而不是在枚举中定义一个。所以我仍然在枚举方面:)。
    • @Prine - 是的,我过去曾多次使用基于地图的方法,但与您使用枚举所做的相比,它没有任何好处(可能的例外:您可以添加新条目在运行时动态映射到地图,和/或删除现有的地图),所以我没有提出来。下次我需要它时,我可能会尝试您的基于枚举的想法。
    【解决方案2】:

    使用枚举列出当前的实现有许多非常好的属性。例如。很容易找到所有当前的实现,因为根据定义,它们必须列在枚举声明中,并且您拥有标准的enum 接口来访问这些实现。

    但这也使得以可插入的方式扩展当前集合成为不可能——因此第 3 方无法添加新的实现。出于这个原因,我通常喜欢使用一个包含所有实现的单例管理器。这种模式也可以很好地与 OSGi 等许多组件框架配合使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 2011-07-17
      • 1970-01-01
      • 2017-07-28
      • 2019-06-03
      • 2012-01-30
      相关资源
      最近更新 更多