2015-02-06 77 views
2

在工作中,我们对代码进行了同行评审,发现了一些我不喜欢的内容,并且想要询问有关此特定问题的最佳实践。带有getter的公共静态final变量

我们有一个接口:

public interface Item { 
    public String getType(); 
    //some other methods 
} 

和实现类:

public class EmailItem implements Item { 
    public static final String TYPE = "email"; 

    @Override 
    public String getType() { 
     return TYPE; 
    } 
} 

和使用类的一些代码:

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

在这一点上,我们只有一个实现类,所以检查类型是没有必要的,但我们会添加一些其他的实现,然后它会有道理(虽然将使用switch)。

主要问题是EmailItem变量TYPE设置为公共,并且此变量也有一个getter。

该类的类和实例都应该有权访问此变量,但拥有它并直接使用实例访问该变量似乎不是正确/最佳实践(虽然技术上可行),并且它将是私有的因为它应该),那么它将无法从其他类访问(其中for周期和静态在这一点上是没有意义的)。

通过讨论,我们提出了使用instanceOf(...)instance.getClass().getName()EmailItem.class.getName()的解决方案,但它们都不显得优雅:)。

因此,最后,我的问题是对于所描述的问题最优雅的解决方案是什么?

嘿,这是我的第一个问题,我希望它对你有意义;)。

+0

您是否在寻找'instanceof'运算符? – immibis 2015-02-06 11:25:12

+2

为什么TYPE是一个字符串而不是枚举? – 2015-02-06 11:26:39

+0

正如我张贴我知道instanceOf(),但我正在寻找programmatical干净的解决方案。 – sycho 2015-02-06 11:27:19

回答

1

你做的是好的,如果你想这样做的方式:

  • static final变量TYPE可让您将其视为类型常量,
  • 实例上的实现允许您根据接口上的返回值检查常量。

但是,当你发现自己派遣由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); 
     } 
    } 
} 
3

它从一个角度OO点思考我会考虑以下方法:

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

如果所有的“类型”为你的Item已知在编译时,您可以使用像这样的枚举:

public interface Item { 
    enum ItemType { MAIL, OTHER; } 

    public ItemType getType(); 
    //some other methods 
}