Инструменты пользователя

Инструменты сайта


php:shablony_proektirovanija:behavioral_patterns:state

Состояние (State)

▶ code

Состояние - инкапсулирует изменение поведения одних и тех же методов в зависимости от состояния объекта. Этот паттерн поможет изящным способом изменить поведение объекта во время выполнения не прибегая к большим монолитным условным операторам.

Использование шаблона «Состояние» локализует зависящее от состояния поведение и делит его на части, соответствующие состояниям, переходы между состояниями становятся явными, а процесс работы с объектом – более прозрачным и понятным.

Использование:

  • Когда у вас есть объект, поведение которого кардинально меняется в зависимости от внутреннего состояния, причём типов состояний много, и их код часто меняется.
  • Когда код класса содержит множество больших, похожих друг на друга, условных операторов, которые выбирают поведения в зависимости от текущих значений полей класса.
  • Когда вы сознательно используете табличную машину состояний, построенную на условных операторах, но вынуждены мириться с дублированием кода для похожих состояний и переходов.

Преимущества:

  • Избавляет от множества больших условных операторов машины состояний.
  • Концентрирует в одном месте код, связанный с определённым состоянием.
  • Упрощает код контекста.

Недостатки:

  • Может неоправданно усложнить код, если состояний мало и они редко меняются.

Связи с другими паттернами

  • Мост, Стратегия и Состояние (а также слегка и Адаптер) имеют схожие структуры классов – все они построены на принципе «композиции», то есть делегирования работы другим объектам. Тем не менее, они отличаются тем, что решают разные проблемы. Помните, что паттерны – это не только рецепт построения кода определённым образом, но и описание проблем, которые привели к данному решению.
  • Состояние можно рассматривать как надстройку над Стратегией. Оба паттерна используют композицию, чтобы менять поведение основного объекта, делегируя работу вложенным объектам-помощникам. Однако в Стратегии эти объекты не знают друг о друге и никак не связаны. В Состоянии сами конкретные состояния могут переключать контекст.

State.php

<?php
 
interface State
{
    public function toNext(Task $task);
 
    public function getStatus();
}
 
class Task
{
    private State $state;
 
    public function getState(): State
    {
        return $this->state;
    }
 
    public function setState(State $state): void
    {
        $this->state = $state;
    }
 
    public static function make(): Task
    {
        $self = new self();
        $self->setState(new Created());
        return $self;
    }
 
    public function proceedToNext(): void
    {
        $this->state->toNext($this);
    }
 
    public function toString()
    {
        return $this->state->getStatus();
    }
 
}
 
class Created implements State
{
 
    public function toNext(Task $task)
    {
        $task->setState(new Process());
    }
 
    public function getStatus(): string
    {
        return 'Created';
    }
}
 
class Process implements State
{
 
    public function toNext(Task $task)
    {
        $task->setState(new Test());
    }
 
    public function getStatus(): string
    {
        return 'Process';
    }
}
 
class Test implements State
{
 
    public function toNext(Task $task)
    {
        $task->setState(new Done());
    }
 
    public function getStatus(): string
    {
        return 'Test';
    }
}
 
class Done implements State
{
 
    public function toNext(Task $task)
    {
    }
 
    public function getStatus(): string
    {
        return 'Done';
    }
}
 
$task = Task::make();
 
$task->proceedToNext();
$task->proceedToNext();
 
//echo $task->getState()->getStatus(); // Test
echo $task->toString(); // Test
 
// ----------- 2 -----------
 
interface WritingState
{
    public function write(string $words);
}
 
class UpperCase implements WritingState
{
    public function write(string $words)
    {
        echo strtoupper($words);
    }
}
 
class LowerCase implements WritingState
{
    public function write(string $words)
    {
        echo strtolower($words);
    }
}
 
class Defaulted implements WritingState
{
    public function write(string $words)
    {
        echo $words;
    }
}
 
class TextEditor
{
    protected $state;
 
    public function __construct(WritingState $state)
    {
        $this->state = $state;
    }
 
    public function setState(WritingState $state)
    {
        $this->state = $state;
    }
 
    public function type(string $words)
    {
        $this->state->write($words);
    }
}
 
$editor = new TextEditor(new Defaulted());
 
$editor->type('First line');
 
$editor->setState(new UpperCase());
 
$editor->type('Second line');
$editor->type('Third line');
 
$editor->setState(new LowerCase());
 
$editor->type('Fourth line');
$editor->type('Fifth line');
 
// Output:
// First line
// SECOND LINE
// THIRD LINE
// fourth line
// fifth line
php/shablony_proektirovanija/behavioral_patterns/state.txt · Последние изменения: 2023/08/17 23:26 — werwolf