Состояние (шаблон проектирования)

Материал из Seo Wiki - Поисковая Оптимизация и Программирование
Перейти к навигацииПерейти к поиску

Состояние (англ. State) — шаблон проектирования. Используется в тех случаях, когда во время выполнения программы объект должен менять свое поведение в зависимости от своего состояния.

Паттерн состоит из 3 блоков:

Widget — класс, объекты которого должны менять свое поведение в зависимости от состояния.

IState — интерфейс, который должно реализовать каждое из конкретных состояний. Через этот интерфейс объект Widget взаимодействует с состоянием, делегируя ему вызовы методов. Интерфейс должен содержать средства для обратной связи с объектом, поведение которого нужно изменить. Для этого используется событие (паттерн Publisher — Subscriber). Это необходимо для того, чтобы в процессе выполнения программы заменять объект состояния при появлении событий. Возможны случаи, когда сам Widget периодически опрашивает объект состояние на наличие перехода.

StateA … StateZ — классы конкретных состояний. Должны содержать информацию о том, при каких условиях и в какие состояния может переходить объект из текущего состояния. Например, из StateA объект может переходить в состояние StateB и StateC, а из StateB — обратно в StateA и так далее. Объект одного из них должен содержать Widget при создании.

Примеры

Javascript

Пример со сменой состояний из State. <source lang="javascript"> // "интерфейс" State

function State() { this.someMethod = function() { }; this.nextState = function() { }; }


// реализация State

// первое состояние function StateA(widjet) { var dublicate = this; // ссылка на инстанцирующийся объект (т.к. this может меняться)

this.someMethod = function() { alert("StateA.someMethod"); dublicate.nextState(); }; this.nextState = function() { alert("StateA > StateB"); widjet.onNextState( new StateB(widjet) ); }; } StateA.prototype = new State(); StateA.prototype.constructor = StateA;

// второе состояние function StateB(widjet) { var dublicate = this;

this.someMethod = function() { alert("StateB.someMethod"); dublicate.nextState(); }; this.nextState = function() { alert("StateB > StateA"); widjet.onNextState( new StateA(widjet) ); }; } StateB.prototype = new State(); StateB.prototype.constructor = StateB;


// "интерфейс" Widget

function Widget() { this.someMethod = function() { }; this.onNextState = function(state) { }; }


// реализация Widget

function Widget1() { var state = new StateA(this);

this.someMethod = function() { state.someMethod(); }; this.onNextState = function(newState) { state = newState; }; } Widget1.prototype = new Widget(); Widget1.prototype.constructor = Widget1;


// использование

var widget = new Widget1(); widget.someMethod(); // StateA.someMethod

                    // StateA > StateB

widget.someMethod(); // StateB.someMethod

                    // StateB > StateA

</source>

Смена состояний с помощью вызова метода у Widget (из англоязычной версии статьи). <source lang="javascript"> // "интерфейс" State

function AbstractTool() { this.moveTo = function(x, y) { }; this.mouseDown = function(x, y) { }; this.mouseUp = function(x, y) { }; }


// реализация State

// инструмент "карандаш" function PenTool(widjet) { var dublicate = this; // ссылка на инстанцирующийся объект (т.к. this может меняться) var mouseIsDown = false; // кнопка мыши сейчас не нажата var lastCoords = []; // прошлые координаты курсора мыши

this.moveTo = function(x, y) { if (mouseIsDown && lastCoords.length) { drawLine(lastCoords, [x, y]); } lastCoords = [x, y]; }; this.mouseDown = function(x, y) { mouseIsDown = true; lastCoords = [x, y]; }; this.mouseUp = function(x, y) { mouseIsDown = false; };

function drawLine(coords1, coords2) { alert("drawLine: ["+ coords1[0] +", "+ coords1[1] +"] - ["+ coords2[0] +", "+ coords2[1] +"]"); }

} PenTool.prototype = new AbstractTool(); PenTool.prototype.constructor = PenTool;

// инструмент "выделение области" function SelectionTool(widget) { var dublicate = this; // ссылка на инстанцирующийся объект (т.к. this может меняться) var mouseIsDown = false; // кнопка мыши сейчас не нажата var startCoords = []; // координаты курсора мыши при нажатии на кнопку

this.moveTo = function(x, y) { if (mouseIsDown) { setSelection(startCoords, [x, y]); } }; this.mouseDown = function(x, y) { startCoords = [x, y]; mouseIsDown = true; }; this.mouseUp = function(x, y) { mouseIsDown = false; };

function setSelection(coords1, coords2) { alert("setSelection: ["+ coords1[0] +", "+ coords1[1] +"] - ["+ coords2[0] +", "+ coords2[1] +"]"); } }; SelectionTool.prototype = new AbstractTool(); SelectionTool.prototype.constructor = SelectionTool;


// реализация Widget

function DrawingController() { var currentTool = new SelectionTool(); // активный инструмент

this.moveTo = function(x, y) { currentTool.moveTo(x, y); }; this.mouseDown = function(x, y) { currentTool.mouseDown(x, y); }; this.mouseUp = function(x, y) { currentTool.mouseUp(x, y); };

this.selectPenTool = function() { // выбираем инструмент "выделение области" currentTool = new PenTool(); }; this.selectSelectionTool = function() { // выбираем инструмент "карандаш" currentTool = new SelectionTool(); }; }

var widget = new DrawingController();

widget.mouseDown(1, 1); widget.moveTo(1, 2); // setSelection: [1, 1] - [1, 2] widget.moveTo(1, 3); // setSelection: [1, 1] - [1, 3] widget.mouseUp(1, 3); widget.moveTo(1, 4);

widget.selectPenTool(); widget.mouseDown(1, 1); widget.moveTo(1, 2); // drawLine: [1, 1] - [1, 2] widget.moveTo(1, 3); // drawLine: [1, 2] - [1, 3] widget.mouseUp(1, 3); widget.moveTo(1, 4); </source>


bg:Състояние (шаблон) cs:Návrhový vzor Stav de:Zustand (Entwurfsmuster) en:State pattern es:State (patrón de diseño) fr:État (patron de conception) pl:Stan (wzorzec projektowy) uk:Стан (шаблон проектування)

Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....