Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative for instanceOf (State Pattern)

I'm having a problem using the state pattern, I don't know how to check if a State is of a certain instance without using instanceOf (because that is considered a bad practice).

TCPConnection holds a TCPState object. Let's say I want to get all the TCPConnections that have the state TCPEstablished. How would I do this? enter image description here

A way would be:

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

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

  return list;
}

But this uses instanceOf and I would prefer not to use that. Are there any better ways? Or is my use of instanceOf valid?

like image 487
Stanko Avatar asked Feb 11 '23 08:02

Stanko


1 Answers

Yes, the use of instanceOf is considered a smell. Furhermore, checking for the type of a state object goes contrary to the idea of the state pattern itself (encapsulate state-dependant behavior in the subtypes such that such checks become unnecessary).

Nevertheless you could technically get rid of the instanceOf by adding another operation to TCPState, e.g. bool isEstablished(), and implement it such that it returns true only on TCPEstablished.

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

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

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

Add the operation to TCPConnection:

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

Then your operation getAllEstablished would look like this:

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

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

    return list;
}

instanceOf is gone. But is it worth it?

like image 103
proskor Avatar answered Feb 13 '23 06:02

proskor