【发布时间】:2013-08-02 13:29:28
【问题描述】:
在 Java 中,函数对象是无状态对象的实例(通常是实现策略接口的单例),其方法对其他对象的状态进行操作。这些是 Java 的等价物,相当于将函数指针作为参数传递给方法,就像在 C 等语言中所做的那样。
1.5 中引入的 Java 枚举规范使程序员能够通过将策略“接口”指定为枚举声明中的一系列抽象方法声明来复制函数对象模式,然后必须为每个枚举常量实现这些声明。
因此,如果要将特定于常量的行为与枚举常量相关联,至少有两种选择:
您可以先声明
Enumimplement您的策略接口,然后将行为作为函数对象存储在最终的enum实例字段中。然后,客户端代码可以通过enum字段访问器方法调用该行为。您可以在
Enum声明中将“策略”声明为一个或多个abstract方法。编译器会坚持为每个enum常量实现这些。然后,客户端代码可以通过enum常量直接调用该方法来调用该行为。
在我看来,函数对象方法需要更多资源。需要在堆上分配对象,对于大型枚举,这可能是几个对象。通过访问器调用的需求似乎需要更慢的执行速度,但是我猜现代 JVM 实现会足够聪明,可以内联方法调用,从而使两种模式的执行速度相似。
我目前使用函数对象来为我编写的 JDBC 数据库应用程序指定“动态”元数据。这些对象描述了数据库的某些特性,例如列和行不变量、用于创建与枚举类对应的数据模型对象的工厂、用于获取和改变数据模型对象数据的访问器以及其他类似的元数据。
这种方法确实需要大量样板文件。很多样板。
虽然使用特定于常量的方法并不能保证消除样板文件,但这种方法应该更简洁易读......并且可能更有效。
我应该重构我的枚举设计以使用特定于常量的方法来代替函数对象吗?
【问题讨论】:
-
+1 个问题,但您应该了解所查看的每件事的延迟规模,并首先优化最大的延迟。
-
当我的策略集未关闭时,我使用枚举的“函数对象”方法;枚举提供了“众所周知的”策略,但策略消费者是针对接口编写的,如果需要,客户端可以实现自己的策略,而不是使用众所周知的策略之一。如果无法实现新策略,则接口没有任何作用,您应该为每个枚举使用特定于常量的实现。
-
@erickson:这真是一个绝妙的建议。谢谢你。