lundi 18 octobre 2021

State Pattern: Changing object behavior based on more than one field and consistency between their values and state value

I'm Trying to learn about State Pattern.

In most of State Pattern examples that I have seen, methods of class change their behavior based on just one field (I mean before applying State Pattern and I'm not talking about the reference field of the state interface type) and also that field has no other use in that class and after applying the State pattern, they delete that.

but in my class, I have 2 fields (x and y) that based on their values, the print() method changes its behavior. and also I use both of these fields in some business logic methods.

This is my FunClass.

public class FunClass {
    private int x;
    private int y;

    public MyClass(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void print() {
        if (x == 1 && y == 1) {
            System.out.println("XY");
        } else if (x == 1 && y == 0) {
            System.out.println("X");
        } else if (x == 0 && y == 1) {
            System.out.println("Y");
        } else if (x == 0 && y == 0) {
            System.out.println("nothing");
        }
    }
    
    // implement some business logic.
    public int sum() {
        return x + y;
    }

    //Setters And Getters ...
}

the print() method behaves differently based on the internal state of an object (by internal state, I mean fields x and y).

so I applied the State Pattern on this class for this method:

public class FunClass {

    private int x;
    private int y;

    private State xyState;

    public FunClass(int x, int y) {
        this.x = x;
        this.y = y;

        if (x == 1 && y == 1) {
            xyState = new XY();
        } else if (x == 1 && y == 0) {
            xyState = new X();
        } else if (x == 0 && y == 1) {
            xyState = new Y();
        } else if (x == 0 && y == 0) {
            xyState = new Nothing();
        }
    }

    public void print() {
        xyState.handlePrint(); //delegate to xyState to handle the request.
    }

    // implement some business logic.
    public int sum() {
        return x + y;
    }

    public void setX(int x) {
        this.x = x;

        if (x == 1 && this.y == 1) {
            xyState = new XY();
        } else if (x == 1 && this.y == 0) {
            xyState = new X();
        } else if (x == 0 && this.y == 1) {
            xyState = new Y();
        } else if (x == 0 && this.y == 0) {
            xyState = new Nothing();
        }
    }

    public void setY(int y) {
        this.y = y;

        if (this.x == 1 && y == 1) {
            xyState = new XY();
        } else if (this.x == 1 && y == 0) {
            xyState = new X();
        } else if (this.x == 0 && y == 1) {
            xyState = new Y();
        } else if (this.x == 0 && y == 0) {
            xyState = new Nothing();
        }
    }
    public void setXyState(State xyState) {
        this.xyState = xyState;
    
        if (xyState instanceof X) {
           this.x = 1;
           this.y = 0;
        } else if (xyState instanceof Y) {
           this.x = 0;
           this.y = 1;
        } else if (xyState instanceof XY) {
           this.x = 1;
           this.y = 1;
        } else if (xyState instanceof Nothing) {
           this.x = 0;
           this.y = 0;
        }
    }

    //Setters And Getters ...
}

I declared the State interface and In FunClass (which is Context), I added a reference field of the state interface type and a public setter that allows overriding the value of that field. and then I added 4 classes (X , Y , XY , Nothing) that have implemented State interface.

But look at my constructor and my setters. I wanted the state implementation to be selected based on x and y values (values of state field and some other fields(x and y) are related And there must be consistency between their values.) and I had to add those if-else statements. And it looks like I'm back to the same problem. even worse!

What should be done now with these conditions? Is this an example of misuse of State Pattern or not? Can we apply the State pattern at the same time and get rid of the conditions?

Aucun commentaire:

Enregistrer un commentaire