首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >替代instanceOf (状态模式)

替代instanceOf (状态模式)
EN

Stack Overflow用户
提问于 2015-04-23 17:49:06
回答 2查看 2.6K关注 0票数 4

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

TCPConnection持有一个TCPState对象。假设我想得到所有具有状态TCPConnectionsTCPEstablished。我该怎么做?

一种办法是:

代码语言:javascript
复制
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的使用有效吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-23 18:07:44

是的,instanceOf的使用被认为是一种气味。此外,检查状态对象的类型违背了状态模式本身的思想(在子类型中封装状态依赖行为,这样就没有必要进行这种检查)。

不过,从技术上讲,您可以通过向instanceOf添加另一个操作(例如bool isEstablished())来摆脱bool isEstablished(),并实现它,使其只在TCPEstablished上返回true

代码语言:javascript
复制
interface TCPState {
    ...
    boolean isEstablished();
}

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

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

将操作添加到TCPConnection

代码语言:javascript
复制
class TCPConnection {
    ...
    boolean isEstablished() {
        return this.getState().isEstablished();
    }
}

那么您的getAllEstablished操作将如下所示:

代码语言:javascript
复制
List<TCPConnection> getAllEstablished() {
    List<TCPConnection> list = new ArrayList<TCPConnection>();

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

    return list;
}

instanceOf走了。但值得吗?

票数 5
EN

Stack Overflow用户

发布于 2015-04-23 17:53:01

你可以把你的州变成一个国家

代码语言:javascript
复制
public enum TCPState{
  ESTABLISHED,
  LISTEN,
  CLOSED;

  ..methods go here

}

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

代码语言:javascript
复制
for(TCPConnection tcp : allConnections) {
  if(tcp.getState()==TCPState.Established)) {
      list.add(tcp);
  }
}

编辑

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

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

代码语言:javascript
复制
public enum TCPState{
  ESTABLISHED,
  LISTEN,
  CLOSED;

 public abstract void foo();

}

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

代码语言:javascript
复制
 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,然后只在需要执行不同操作的值中使用重写。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29830832

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档