繁体   English   中英

通过枚举值或其实现接口区分实现接口的对象实例

[英]Distinguish instances of objects implementing an interface, by an enum value or by its implementing interface

情况是我有这个界面:

interface ISymbol
{

}

这些类:

class Letter implements ISymbol
{

}

class Number implements ISymbol
{

}

class LowerCaseLetter extends Letter
{

}

class UpperCaseLetter extends Letter
{

}

现在让我们说我在另一个类中具有此功能。 此类执行的逻辑不属于ISymbol类的实现:

class SymbolMonitor
{
void func(ISymbol[] symbols)
{
    for (ISymbol iSymbol : symbols)
    {
        // If the symbol is a number 
        // or a lower case letter do something.
    }
}
}

但是我不想专门检查这两种类型,因为我可能还有其他实现类的ISymbol,它们也需要相同的逻辑。

我的问题是关于首选的行动方式。 我有两种解决方法。 1.创建一个这样的:

enum SymbolType
{
    NORMAL,
    SPECIAL1,
    SPECIAL2,
}

并添加到代码中:

    interface ISymbol
{
    SymbolType getType();
}

class SymbolMonitor
{
    void func(ISymbol[] symbols)
{
    for (ISymbol iSymbol : symbols)
    {
            if(iSymbol.getType().equals(SymbolType.SPECIAL1))
                    {
                        // Do special1 logic
                    }
            if(iSymbol.getType().equals(SymbolType.SPECIAL2))
                    {
                        // Do special2 logic
                    }
    }
}
}
  1. 我可以创建空接口并使用instanceof函数。

     interface ISpecialSymbol1 

    {

    }

    接口ISpecialSymbol2 {

    }

    class LowerCaseLetter扩展Letter实现ISpecialSymbol1 {

    }

    类Number实现ISymbol,ISpecialSymbol1 {

    }

这样该函数将是:

class SymbolMonitor
{
void func(ISymbol[] symbols)
{
    for (ISymbol iSymbol : symbols)
    {
        if(iSymbol instanceof ISpecialSymbol1)
        {
            // Do special 1 logic.
        }
        if(iSymbol instanceof ISpecialSymbol2)
        {
            // Do special 2 logic.
        }
    }
}
}

我认为第二个选项要简单得多,但是我对Java还是陌生的,我完全不确定使用哪种正确的操作方式。

在接口中声明一个方法:

interface ISymbol
{
   public void doSomething();
}

并且任何实现类都可以覆盖并指定其所需的行为。 在这种情况下:

class Letter implements ISymbol
{
    public void doSomething() {
         //do Nothing
    }
}

class Number implements ISymbol
{
     public void doSomething() {
         //do Something
    }
}

class LowerCaseLetter extends Letter
{
    public void doSomething() {
         //do Something
    }
}

class UpperCaseLetter extends Letter
{
    public void doSomething() {
         //do Nothing
    }
}

然后您可以直接调用ISymbol.doSomething()

void func(ISymbol[] symbols)
{
    for (ISymbol iSymbol : symbols)
    {
        iSymbol.doSomething()
    }
}

您的问题是“ 设计模式:可重用的面向对象软件的元素 ”中对访客模式给出的动机的几乎逐字引用。 在代码中,这将类似于:

interface Visitor {
    void visit(Letter letter);
    void visit(Number number);
    // ...
}

interface ISymbol {
    void visit(Visitor v);
}

class Letter {
    @Override void visit(Visitor v) {
        v.visit(this);
    }
}

class Number {
    @Override void visit(Visitor v) {
        v.visit(this);
    }
}

如果访问者可以保持对操作类型的了解,则可以使用枚举(因为访问者仅使用所有Symbol具有的方法)。 如果访问者确实需要转换为相应的符号类型,则我希望使用访问者模式。

我通常更喜欢访问者模式,而不是一系列的instanceof检查,因为访问者模式使编译器可以验证所有访问者都可以处理所有符号类型-因此,如果添加符号类型,则所有现有访问者都将不再编译,直到您指定了如何处理这种新类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM