Accueil / Tutoriels / State : Gérer élégamment les changements de comportement
State : Gérer élégamment les changements de comportement
Publié le 16 Juin 2025State est un design pattern comportemental qui permet de gérer proprement les changements de comportement d’un objet en fonction de son état interne. Plutôt que d’enchaîner des conditions if, else ou des blocs switch, le pattern State propose une approche orientée objet : chaque état devient une classe à part entière, responsable de son propre comportement et de ses transitions.
Ce pattern est particulièrement utile en développement web, où de nombreux objets évoluent selon un cycle de vie bien défini. Une commande peut passer de “en attente” à “ expédiée”, un utilisateur de “visiteur” à “abonné”, une session de “valide” à “expirée”. Plutôt que d’alourdir le code métier avec des vérifications d’état éparpillées, le pattern State apporte structure, lisibilité et extensibilité.
Principe du pattern State
Cas d’utilisation en programmation web
Gérer le cycle de vie d’une commande e-commerce
Implémenter un workflow utilisateur dynamique
Points d’attentions
Implémenter le pattern State
Voici un exemple en Go :
package userstate
type UserState interface {
ViewDashboard()
Upgrade(user *User)
}
package userstate
import "fmt"
type GuestState struct{}
func (g *GuestState) ViewDashboard() {
fmt.Println("Accès limité. Connectez-vous pour plus de fonctionnalités.")
}
func (g *GuestState) Upgrade(user *User) {
fmt.Println("Passage à l'état Utilisateur enregistré.")
user.SetState(&RegisteredState{})
}
type RegisteredState struct{}
func (r *RegisteredState) ViewDashboard() {
fmt.Println("Bienvenue sur votre tableau de bord utilisateur.")
}
func (r *RegisteredState) Upgrade(user *User) {
fmt.Println("Passage à l'état Abonné premium.")
user.SetState(&PremiumState{})
}
type PremiumState struct{}
func (p *PremiumState) ViewDashboard() {
fmt.Println("Bienvenue dans votre espace premium avec toutes les fonctionnalités.")
}
func (p *PremiumState) Upgrade(user *User) {
fmt.Println("Vous êtes déjà au niveau maximum.")
}
package userstate
type User struct {
state UserState
}
func NewUser(initialState UserState) *User {
return &User{state: initialState}
}
func (u *User) SetState(state UserState) {
u.state = state
}
func (u *User) ViewDashboard() {
u.state.ViewDashboard()
}
func (u *User) Upgrade() {
u.state.Upgrade(u)
}
package main
import "training.go/designpatterns/state/userstate"
func main() {
user := userstate.NewUser(&userstate.GuestState{})
user.ViewDashboard()
user.Upgrade()
user.ViewDashboard()
user.Upgrade()
user.ViewDashboard()
user.Upgrade()
}
Le même exemple en PHP :
namespace Practice\DesignPatterns\State;
interface UserStateInterface
{
public function viewDashboard();
public function upgrade(User $user);
}
namespace Practice\DesignPatterns\State;
class User {
private UserStateInterface $state;
public function __construct(UserStateInterface $state) {
$this->state = $state;
}
public function setState(UserStateInterface $state): void {
$this->state = $state;
}
public function viewDashboard(): void {
$this->state->viewDashboard();
}
public function upgrade(): void {
$this->state->upgrade($this);
}
}
namespace Practice\DesignPatterns\State;
class GuestState implements UserStateInterface
{
public function viewDashboard(): void {
echo "Accès limité. Connectez-vous pour plus de fonctionnalités.\n";
}
public function upgrade(User $user): void {
echo "Passage à l'état Utilisateur enregistré.\n";
$user->setState(new RegisteredState());
}
}
namespace Practice\DesignPatterns\State;
class PremiumState implements UserStateInterface
{
public function viewDashboard(): void {
echo "Bienvenue dans votre espace premium avec toutes les fonctionnalités.\n";
}
public function upgrade(User $user): void {
echo "Vous êtes déjà au niveau maximum.\n";
}
}
namespace Practice\DesignPatterns\State;
class RegisteredState implements UserStateInterface
{
public function viewDashboard(): void {
echo "Bienvenue sur votre tableau de bord utilisateur.\n";
}
public function upgrade(User $user): void {
echo "Passage à l'état Abonné premium.\n";
$user->setState(new PremiumState());
}
}
declare(strict_types=1);
use Practice\DesignPatterns\State\GuestState;
use Practice\DesignPatterns\state\User;
require "./vendor/autoload.php";
$user = new User(new GuestState());
$user->viewDashboard();
$user->upgrade();
$user->viewDashboard();
$user->upgrade();
$user->viewDashboard();
$user->upgrade();