Public 带有 getter 的静态最终变量
Public static final variable with getter
在工作中,我们对代码进行了同行评审,我发现了一些我不喜欢的东西,我想询问针对这个特定问题的最佳实践。
我们有一个界面:
public interface Item {
public String getType();
//some other methods
}
和一个实现 class:
public class EmailItem implements Item {
public static final String TYPE = "email";
@Override
public String getType() {
return TYPE;
}
}
和一些使用 classes 的代码:
for (Item item : items) {
if (EmailItem.TYPE.equals(item.getType())) {
isProcessed = Processor.process(item);
} else {
LOGGER.error("Unknown failover type received to process. Type: {}", item.getType());
}
}
此时我们只有一个实现 class,因此不需要检查类型,但我们将添加一些其他实现,然后它才有意义(尽管将使用 switch
)。
主要问题是 EmailItem
将变量 TYPE
设置为 public 并且此变量还有一个 getter.
class 和那个 class 的实例都应该可以访问这个变量,但是拥有它 public static final
并直接用实例访问它似乎 right/best实践(尽管这在技术上是可行的)并且当它是私有的(它应该)时,它就不能从其他 classes 访问(其中 for
循环是静态的,在那个点)。
通过讨论,我们提出了使用 instanceOf(...)
或 instance.getClass().getName()
和 EmailItem.class.getName()
的解决方案,但其中 none 对我来说似乎很优雅 :).
最后,我的问题是,对于所描述的问题,最优雅的解决方案是什么?
嘿,这是我的第一个问题,我希望它对你有意义 ;)。
从面向对象的角度考虑,我会考虑以下方法:
public interface Item {
public boolean process();
//some other methods
}
public class EmailItem implements Item {
@Override
public boolean process() {
// email specific implementation
}
}
public class AnotherItem implements Item {
@Override
public boolean process() {
// another implementation
}
}
for (Item item : items) {
isProcessed = item.process();
}
你这样做的方式很好,如果你想这样做的话:
static final
变量 TYPE
让你把它当作类型常量,
- 实例上的实现允许您根据接口上的 return 值检查常量。
但是,当您发现自己在 String
或其他值表示的类型上进行调度时,您通常会走上面向对象代码中 switch
语句的错误路径。如果此时您可以选择操作,请考虑双重分派的替代技术,例如实现 Visitor Pattern:
interface ItemVisitor {
void visitEmail(EmailItem item);
void visitSms(SmsItem item);
}
interface Item {
void accept(ItemVisitor v);
}
class EmailItem implements Item {
public void accept(ItemVisitor v) { v.visitEmail(this); }
}
class SmsItem implements Item {
public void accept(ItemVisitor v) { v.visitSms(this); }
}
现在你可以这样做了:
class Example implements ItemVisitor {
public void visitEmail(EmailItem item) {
// Do something with an e-mail
}
public void visitSms(SmsItem item) {
// Do something with an SMS
}
public static void main(String[] args) {
Example e = new Example();
for (Item item : ItemSource.getManyItems()) {
item.accept(e);
}
}
}
如果您的 Item
的所有 "types" 在编译时都是已知的,您可以使用这样的枚举:
public interface Item {
enum ItemType { MAIL, OTHER; }
public ItemType getType();
//some other methods
}
在工作中,我们对代码进行了同行评审,我发现了一些我不喜欢的东西,我想询问针对这个特定问题的最佳实践。
我们有一个界面:
public interface Item {
public String getType();
//some other methods
}
和一个实现 class:
public class EmailItem implements Item {
public static final String TYPE = "email";
@Override
public String getType() {
return TYPE;
}
}
和一些使用 classes 的代码:
for (Item item : items) {
if (EmailItem.TYPE.equals(item.getType())) {
isProcessed = Processor.process(item);
} else {
LOGGER.error("Unknown failover type received to process. Type: {}", item.getType());
}
}
此时我们只有一个实现 class,因此不需要检查类型,但我们将添加一些其他实现,然后它才有意义(尽管将使用 switch
)。
主要问题是 EmailItem
将变量 TYPE
设置为 public 并且此变量还有一个 getter.
class 和那个 class 的实例都应该可以访问这个变量,但是拥有它 public static final
并直接用实例访问它似乎 right/best实践(尽管这在技术上是可行的)并且当它是私有的(它应该)时,它就不能从其他 classes 访问(其中 for
循环是静态的,在那个点)。
通过讨论,我们提出了使用 instanceOf(...)
或 instance.getClass().getName()
和 EmailItem.class.getName()
的解决方案,但其中 none 对我来说似乎很优雅 :).
最后,我的问题是,对于所描述的问题,最优雅的解决方案是什么?
嘿,这是我的第一个问题,我希望它对你有意义 ;)。
从面向对象的角度考虑,我会考虑以下方法:
public interface Item {
public boolean process();
//some other methods
}
public class EmailItem implements Item {
@Override
public boolean process() {
// email specific implementation
}
}
public class AnotherItem implements Item {
@Override
public boolean process() {
// another implementation
}
}
for (Item item : items) {
isProcessed = item.process();
}
你这样做的方式很好,如果你想这样做的话:
static final
变量TYPE
让你把它当作类型常量,- 实例上的实现允许您根据接口上的 return 值检查常量。
但是,当您发现自己在 String
或其他值表示的类型上进行调度时,您通常会走上面向对象代码中 switch
语句的错误路径。如果此时您可以选择操作,请考虑双重分派的替代技术,例如实现 Visitor Pattern:
interface ItemVisitor {
void visitEmail(EmailItem item);
void visitSms(SmsItem item);
}
interface Item {
void accept(ItemVisitor v);
}
class EmailItem implements Item {
public void accept(ItemVisitor v) { v.visitEmail(this); }
}
class SmsItem implements Item {
public void accept(ItemVisitor v) { v.visitSms(this); }
}
现在你可以这样做了:
class Example implements ItemVisitor {
public void visitEmail(EmailItem item) {
// Do something with an e-mail
}
public void visitSms(SmsItem item) {
// Do something with an SMS
}
public static void main(String[] args) {
Example e = new Example();
for (Item item : ItemSource.getManyItems()) {
item.accept(e);
}
}
}
如果您的 Item
的所有 "types" 在编译时都是已知的,您可以使用这样的枚举:
public interface Item {
enum ItemType { MAIL, OTHER; }
public ItemType getType();
//some other methods
}