State Pattern when the Behavior in Object of Type A is Dependent on the State of the Object of Type B

I have used the state pattern for my web application where a user can be in one of three states: activated, required_activation and suspended. I have created 3 states classes as given below (source is in PHP) and a variable named state holds the instance of a state out of 3. class User { private UserState $state; public function __construct() { $this->state = new ActivationRequiredUserState() } } abstract class UserState { public abstract function login(User $user): void; } class ActivatedUserState extends UserState { public function login(User $user): void { // implement login and return token. } } class SuspendedUserState extends UserState { public function login(User $user): void { // throw an exception with message that suspended user can't login. } } class ActivationRequiredUserState extends UserState { public function login(User $user): void { // throw an exception with message that please activate your account before login. } } class UserStateContext { $user = new User(); $user->state->login($this); } So far, so good, I have no issue and it was working fine. The Actual Issue A user belongs to a company and has its own states like activated, required_activation and suspended. When I call $user->state->login() I now have to consider the state of the Company object as well. As it is obvious that if a company is in suspended state then it doesn't matter that whatever state a user in, I have to stop logging in action and throw an error but with an error that the company is suspended NOT DELETED or NOT ARCHIVED. For this I have a solution that out of three UserStates I put a check (if condition) in the ActivatedUserState which will check if the company is not in suspended state as given below: class ActivatedUserState extends UserState { public function login(User $user): void { if($company->status !== 'suspended') { // implement login and return token. } else { // throw an error with the message the company is suspended. } } } But this then introduces the if/else and will make it more and more complex if my company object has few more states. NOTE: This question is very much related to this one which has the following two parts: Should I use the State Design pattern for only two states? Also, what if one object's state is affected by another state? According to the question asker part 1 of the question is answered which easy for me and I already have implemented more than 2 states for my User and Company objects. But part 2 of his question, which similar to my question is not answered as Sean had mentioned in the comments of the answer (which is incomplete answer).

Apr 19, 2025 - 16:10
 0
State Pattern when the Behavior in Object of Type A is Dependent on the State of the Object of Type B

I have used the state pattern for my web application where a user can be in one of three states: activated, required_activation and suspended. I have created 3 states classes as given below (source is in PHP) and a variable named state holds the instance of a state out of 3.

class User {
    private UserState $state;
    public function __construct()
    {
        $this->state = new ActivationRequiredUserState()
    }
}


abstract class UserState {
    public abstract function login(User $user): void;
}


class ActivatedUserState extends UserState {
    public function login(User $user): void {
        // implement login and return token.
    }
}

class SuspendedUserState extends UserState {
    public function login(User $user): void {
        // throw an exception with message that suspended user can't login.
    }
}

class ActivationRequiredUserState extends UserState {
    public function login(User $user): void {
        // throw an exception with message that please activate your account before login.
    }
}

class UserStateContext {
    $user = new User();

    $user->state->login($this);
}

So far, so good, I have no issue and it was working fine.

The Actual Issue

A user belongs to a company and has its own states like activated, required_activation and suspended. When I call $user->state->login() I now have to consider the state of the Company object as well. As it is obvious that if a company is in suspended state then it doesn't matter that whatever state a user in, I have to stop logging in action and throw an error but with an error that the company is suspended NOT DELETED or NOT ARCHIVED.

For this I have a solution that out of three UserStates I put a check (if condition) in the ActivatedUserState which will check if the company is not in suspended state as given below:

class ActivatedUserState extends UserState {
    public function login(User $user): void {
        if($company->status !== 'suspended') {
            // implement login and return token.
        } else {
            // throw an error with the message the company is suspended.
        }
    }
}

But this then introduces the if/else and will make it more and more complex if my company object has few more states.

NOTE: This question is very much related to this one which has the following two parts:

  1. Should I use the State Design pattern for only two states?
  2. Also, what if one object's state is affected by another state?

According to the question asker part 1 of the question is answered which easy for me and I already have implemented more than 2 states for my User and Company objects. But part 2 of his question, which similar to my question is not answered as Sean had mentioned in the comments of the answer (which is incomplete answer).