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).

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).