带有getter的public static final变量

时间:2015-02-06 11:24:29

标签: java interface

在工作中我们对代码进行了同行评审,我发现了一些我不喜欢的东西,我想问一下这个特定问题的最佳实践。

我们有一个界面:

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。

该类的类和实例都应该可以访问这个变量,但是让它public static final并直接用实例访问它并不是正确/最佳实践(尽管技术上可行)并且何时它将是私有的(因为它应该)然后它不能从其他类访问(其中for循环是静态的,并且静态在那时没有意义)。

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

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

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

3 个答案:

答案 0 :(得分: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 :(得分: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);
        }
    }
}

答案 2 :(得分:1)

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

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

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