altO的替代方案(状态模式)

时间:2015-04-23 17:49:07

标签: java design-patterns state instanceof

我在使用状态模式时遇到问题,我不知道如何在不使用State的情况下检查instanceOf是否属于某个实例(因为这被认为是一个不好的做法)。

TCPConnection拥有TCPState个对象。 我们想说我希望得到状态为TCPConnections的所有TCPEstablished。我该怎么做? enter image description here

一种方式是:

public List<TCPConnection> getAllEstablished() {
  List<TCPConnection> list = new ArrayList<TCPConnection>();

  for(TCPConnection tcp : allConnections) {
      if(tcp.getState().instanceOf(TCPEstablished)) {
          list.add(tcp);
      }
  }

  return list;
}

但这会使用instanceOf,我宁愿不使用它。有没有更好的方法?或者我使用instanceOf有效吗?

2 个答案:

答案 0 :(得分:4)

是的,使用instanceOf被认为是一种气味。此外,检查状态对象的类型与状态模式本身的想法相反(在子类型中封装与状态相关的行为,使得这种检查变得不必要)。

尽管如此,您可以通过向instanceOf添加其他操作来从技术上删除TCPState,例如bool isEstablished(),并执行它,使其仅在true上返回TCPEstablished

interface TCPState {
    ...
    boolean isEstablished();
}

class TCPEstablished implements TCPState {
    ...
    boolean isEstablished() {
        return true;
    }
}

class TCPClosed implements TCPState {
    ...
    boolean isEstablished() {
        return false;
    }
}

将操作添加到TCPConnection

class TCPConnection {
    ...
    boolean isEstablished() {
        return this.getState().isEstablished();
    }
}

然后您的操作getAllEstablished将如下所示:

List<TCPConnection> getAllEstablished() {
    List<TCPConnection> list = new ArrayList<TCPConnection>();

    for(TCPConnection tcp : allConnections) {
        if(tcp.isEstablished()) {
            list.add(tcp);
        }
    }

    return list;
}

instanceOf消失了。但它值得吗?

答案 1 :(得分:2)

您可以将状态设为枚举

public enum TCPState{
  ESTABLISHED,
  LISTEN,
  CLOSED;

  ..methods go here

}

由于枚举值是完全成熟的对象,因此它们可以覆盖执行特定状态行为的方法。然后,您可以执行equals()甚至==检查以检查状态。

for(TCPConnection tcp : allConnections) {
  if(tcp.getState()==TCPState.Established)) {
      list.add(tcp);
  }
}

修改

以下是如何使每个枚举值对方法具有不同的实现。

假设TCPState实现了一个接口或者有一个抽象方法foo()

public enum TCPState{
  ESTABLISHED,
  LISTEN,
  CLOSED;

 public abstract void foo();

}

然后,您可以对每个值实现不同的方法,如下所示:

 public enum TCPState{
  ESTABLISHED{
     @Override
     public void foo(){
         System.out.println("established");
     }
  },
  LISTEN{
     @Override
     public void foo(){
         System.out.println("listening");
     }
  },
  CLOSED{
     @Override
     public void foo(){
         System.out.println("closed");
     }
  }
  ;

 public abstract void foo();

}

或者,您可以在TCPSTate中创建基本实现,而不是声明它abstract,然后仅在需要执行不同操作的值中使用覆盖。