Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Dukobpa3

Оценить эту запись

Strategy (Стратегия)

Запись от Dukobpa3 размещена 27.12.2013 в 18:40
Обновил(-а) Dukobpa3 02.01.2014 в 06:45

Ну как обычно затравочка:

Всё тот же сайтик с кодом на плюсах
Всё тот же паттернкрафт с его стратегией

Погнали.
Суть паттерна стратегии в том что у нас к примеру есть некое поведение. Например "заархивировать". Или же "скачать". Или же "двигаться".
В глобальном смысле с точки зрения системы нам побоку КАК мы будем качать. Нам важен конечный результат.
Поэтому мы пытаемся отрезать сам алгоритм поведения от объекта и реализовать его отдельно. Далее вводим опять же как и со стейтом понятие контекста, который будет заниматься определением того КАК именно мы будем качать либо двигаться, т.е. выбором конкретной стратегии из набора.
Если вы начнете гуглить по этому паттерну то наткнетесь на кучу вопросов "чем паттерн стейт отличается от паттерна стратегии". По сути и тот и тот паттерн меняют поведение объекта, и более того - умл диаграмма идентична.
Но тут важно понимать. Стейт без объекта НЕ СУЩЕСТВУЕТ. Стейт это одно из состояний одного КОНКРЕТНОГО объекта.
А стратегии же пофигу даже на сам объект. Это только поведение. В идеале стратегия должна укладываться в один метод.

Саму стратегию неплохо описал ДжонЛингвист в своем паттернкрафте. У нас есть Три каких-то юнита. И есть каких-то 4 способа передвижения. Мы можем этими способами передвижения двигать любой из этих обэектов. Чистая стратегия, всё красиво. Контекста как такового у него в примере нету, в роли контекста выступает документКласс приложения и слушатель клавиатуры.

Рекомендую предварительно ознакомиться с его примером и видео.
Но дабы объяснить разницу между стейтом с тратегией я немного расширил его пример. Добавил к нему код из предыдущего поста о стейтах и постарался показать на примере как в одном коде красиво могут сочетаться стейт и тратегия и в чем между ними разница.

Вот что получилось.
Duk.swf   (42.4 Кб)

На сцене лежат два квадратика. Танк и Ворон.
Кликаем мышкой по "юниту", чотбы выбрать его. Сверху в текстовом поле будет подписано что конкретно мы выбрали.
Далее можем кликнуть мышкой по пустому месту и выбранный юнит туда побежит.
Кнопками 1-3 переключаем стейт текущего выбранного юнита.
Кликом по другому юниту можем поменять выделение.

Вот исходник всего проекта. Приводить его здесь целиком сложно потому что кода много. Остановлюсь только на ключевых моментах.
StateWithStrategy.zip

У нас есть интерфейс абстрактной стратегии передвижения, который описывает метод передвижения. Метод может двигать любой Vechicle(первый параметр) как угодно(второй параметр)
Код AS3:
package patterncraft.move
{
	import patterncraft.Vehicle;
 
 
	public interface IMoveVehicleBehavior
    {
        function move(vehicle:Vehicle, tweenVars:Object):void;
    }
}
У нас есть базовый класс Vehicle В котором предусмотрена возможность переключать стейт и ссылка на нашу конкретную стратегию передвижения.
Код AS3:
package patterncraft
{
	import patterncraft.move.*;
    import flash.display.Sprite;
 
    public class Vehicle extends Sprite
    {
        public var moveBehavior:IMoveVehicleBehavior;
 
        public function move(tweenVars:Object):void
        {
            if (moveBehavior) moveBehavior.move(this, tweenVars);
        }
 
	    public function setState(state:String):void
	    {
			throw new Error("need to override");
	    }
    }
}
Касательно реализации самого танка и ворона всё как в примере со стейтом. Для ворона передрал реализацию танка, немного упростил. И у танка и у ворона убрал лишнее.
Немного поменялась реализация самих стейтов. Теперь стейт не сам реализовывает передвижение. Теперь стейт является контекстом стратегии. На момент транзишина стейт убирает конкретную стратегию из танка. Соответственно танк не может двигаться. Когда стейт установлен - он устанавливает танку конкретную стратегию передвижения, и танк опять может двигаться.
Код AS3:
	internal class SiegeState extends EventDispatcher implements ISiegeTankState {
        private var siegeTank:SiegeTank;
 
        public function SiegeState(siegeTank:SiegeTank) {
            this.siegeTank = siegeTank;
        }
 
        public function get damage():Number { return 20; }
 
        public function get canMove():Boolean { return false; }
 
        public function get color():uint { return 0x00cc00; }
 
		public function apply():void {
			// Когда транзишн закончился мы можем использовать танк по назначению.
			siegeTank.mouseEnabled = true;
			siegeTank.alpha = 1;
 
			// Пристегиваем конкретную стратегию движения
			siegeTank.moveBehavior = new Walk();
		}
 
        public function transitionTo(state:String):void {
	        // Убираем возможность двигаться и отображаем это визуально полупрозрачностью
	        siegeTank.mouseEnabled = false;
	        siegeTank.alpha = 0.3;
	        siegeTank.moveBehavior = null;
 
	        var timer:Timer = new Timer(1000, 1);
			timer.addEventListener(TimerEvent.TIMER, onTransitionComplete);
			timer.start();
		}
 
		private function onTransitionComplete(event:TimerEvent):void {
			event.currentTarget.reset();
			dispatchEvent(new Event(Event.COMPLETE));
		}
    }
Суть этой всей бадяги в том что нам не нужно писать передвижение по воздуху и для танка и для ворона в соответствующих стейтах. Мы можем переиспользовать алгоритм передвижения.
Это не мешает стейтам и это не замена стейту, но как дополнение - вполне подойдет.

Важно понимать, что стратегия не привязана к объекту.
Стейт без объекта не существует.
Стратегия реализовывает какое-то одно абстрактное поведение и несколько его конкретных реализаций для нескольких схожих объектов.
Стейт реализует разное поведение для одного объекта(в нашем кейсе стейт это делает посредством стратегии, хотя могла быть и любая другая реализация).

Вот как-то так. Не уверен что вышло суперпонятно, на вопросы отвечать готов, текст править тоже без проблем. Пока что будем считать задачу выполненной
Вложения
Тип файла: swf Duk.swf (42.4 Кб, 766 просмотров)
Всего комментариев 11

Комментарии

Старый 27.12.2013 18:45 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
И пока со статьями пауза.
Позже думаю рассмотреть фабрику и фабричный метод.
Старый 27.12.2013 18:46 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
В целом уже чуток текста накатал, буду благодарен за конструктивный фидбек по качеству изложения. Не уверен что всё получается понятно описать.
Старый 31.12.2013 13:32 AlexLucas вне форума
AlexLucas
 
Аватар для AlexLucas
Спасибо, очень доступно изложено.
Старый 15.02.2014 23:24 Akopalipsis вне форума
Akopalipsis
Спасибо я уже говорил, но скажу ещё раз - Спасибо!
Цитата:
Позже думаю рассмотреть фабрику и фабричный метод.
Почему-то в памяти осело, что у Вас я смогу посмотреть на Команду, в роли посредника между загрузчиком - сервером, но не нашёл. И вот если будете писать, то было бы здорово увидеть реализацию с очередью и вот, как было в какой-то теме, команда в роли обёртки, которая несет в себе и команду на действие и на ответ..
Старый 16.02.2014 00:23 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
@Akopalipsis
Ты как раз вовремя Я сейчас делаю проект в котором http-Rest протокол
Как раз придумаю как порулить да поделюсь Из готовых наработок, как я там и писал, у меня такого нету, я обычно только с сокетом работал.
Старый 16.02.2014 04:29 Akopalipsis вне форума
Akopalipsis
Dukobpa3 жду с нетерпением
Старый 23.02.2015 12:07 callme вне форума
callme
 
Аватар для callme
Цитата:
Но тут важно понимать. Стейт без объекта НЕ СУЩЕСТВУЕТ. Стейт это одно из состояний одного КОНКРЕТНОГО объекта.
А стратегии же пофигу даже на сам объект. Это только поведение.

Важно понимать, что стратегия не привязана к объекту.
Стейт без объекта не существует.
Если стратегии передается ссылка на контекст, то стратегия привязана к контексту. Если состоянию не передается ссылка на контекст, то состояние не привязано к контексту.

Так что оба паттерна могут быть как привязаны, так и нет.
Старый 23.02.2015 13:46 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Если стратегии нужна ссылка на контекст - скорее всего это стейт.
Старый 23.02.2015 14:10 callme вне форума
callme
 
Аватар для callme
Получается вы никогда не знаете стейт это или стратегия. Лишь основываясь на статистических данных, вы можете предполагать, что если передается контекст, то это скорее стейт чем стратегия.
Старый 23.02.2015 23:24 СлаваRa вне форума
СлаваRa
 
Аватар для СлаваRa
"стейт" - он чей, "стратегия" - она для чего...
Старый 24.02.2015 09:49 callme вне форума
callme
 
Аватар для callme
Стейт ничей. Он реализует интерфейс. Это все, что его интересует.
 

 


Часовой пояс GMT +4, время: 18:58.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.