LINUX.ORG.RU

Подскажите по шаблону стратегия

 , , ,


0

1

Я сегодня разобрал шаблон стратегия, на примере JS вот отсюда

https://ru.wikipedia.org/wiki/Стратегия_(шаблон_проектирования)#.D0.9F.D1.80....

То что там нписано в самой статье, я вобще нихрена не понял, какая-то билеберда. Решил, что по коду пойму. Не понял:) Сам код то я понял, что он делает, собственно, я его даже «улучшил», путем выкидывания разногоо рода говна. Вот что в моей версии получилось

create=Object.create


Strategy={
  exec: function(){},
  message: "foo"
}

Strategy.WindowStatus=create(Strategy)
Strategy.NewWindow=create(Strategy)
Strategy.Alert=create(Strategy)

with(Strategy){
  WindowStatus.exec=function(){status=message}
  NewWindow.exec=function(){
    open("", "_blank").document.write("<html>"+message+"</html>")
  }
  Alert.exec=function(){alert(message)}
}

with(Strategy){
 WindowStatus.exec()
 NewWindow.exec()
 Alert.exec()
}
Этот код делает то же самое, только меньше по объему раза в 3.

Сначала пара вопросов по реализации.

Я пропускаю момент засирания синтаксическим мусором, это ладно, проехали.

Зачем они там наследуют не от самого Strategy, а от его экземпляров? То есть, фактически все эти их подклассы имеют разных родителей. В этом есть какой-то смысл?

Дальше, я не понял, зачем они создают обертку «Context»?

Далее, они зачем-то создают экземпляры для каждого класса, хотя необходимости в этом тоже никакой нет, можно также вызвать эти экзеки из самих классов(что я и сделал), но это, ладно, может быть просто для понта создали экземпляры, не столь важно.

Теперь самый главный вопрос: В ЧЕМ ЗАКЛЮЧАЕТСЯ СТРАТЕГИЯ? Уж не в том ли, чтобы поочередно вызвать 3 функции?

Заранее спасибо.

шаблон стратегия, на примере JS

шаблон ..., на примере JS

js нельзя назвать полноценным ООП. Не советую на нём изучать паттерны.

Tanger ★★★★★ ()
Ответ на: комментарий от Tanger

нельзя назвать полноценным ООП

Ну, полноценным в смысле смолтока, ни один из мейнстримных Яп не назовешь, но уж для изучения паттернов, он ничем не хуже, чем другие.

javaQest ()
Ответ на: комментарий от javaQest

но уж для изучения паттернов, он ничем не хуже, чем другие.

Он гораздо хуже чем другие так как тебе приходится отвлекаться на тонкости реализации, которая, в зависимости от скила костыляния на js стандартных оопешных примитивов, может очень сильно отличаться. А в нормальны ЯП ты спокойно можешь сосредоточиться на абстракциях.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

Во первых, я JS более или менее знаю, а другие еще надо изучать. Причем изучение других не освобождает от JS, он всюду.

Во вторых, мне нравиться, что в JS можно (пока?) писать ООП без сахара. Это существенно облегчает понимание, и придеет гибкости. Даже Смолток сосет, в этом отношении. Так что, с JS все ок. Не ок с пейсателями на нем, в данном случае, я подозреваю. А хотелось бы понять, в чем суть этого шаблона вообще.

javaQest ()

я его даже «улучшил», путем выкидывания разногоо рода говна.

Пора бы улучшить ЛОР, выкинув тебя.

Deleted ()

ru.wikipedia

Ты делаешь это неправильно.

x3al ★★★★★ ()
Ответ на: комментарий от javaQest

Во вторых, мне нравиться, что в JS можно (пока?) писать ООП без сахара. Это существенно облегчает понимание, и придеет гибкости.

В таком случае, почему у тебя так туго идет понимание базовых элементарных вещей?

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

Я не считаю, что у меня что-то идет туго. Я считаю, что либо это шаблон бессмысленный, либо в примере «реализаторы» что-то намудили.

Ты можешь словами объяснить, в чем суть этого шаблона?

javaQest ()
Ответ на: комментарий от javaQest

Я не считаю, что у меня что-то идет туго.

Сними уже розовые очки. Это далеко не первый твой тупой вопрос на лоре, и даже не первый шаблон который ты не осилил, а прогресса 0.

Я считаю, что либо это шаблон бессмысленный, либо в примере «реализаторы» что-то намудили.

шаблону этому сто лет в обед, был бы он бессмысленным ... а похер, считай как хочешь.)

Ты можешь словами объяснить, в чем суть этого шаблона?

Динамически выбирать алгоритм.

TDrive ★★★★★ ()
Ответ на: комментарий от javaQest

От чего угодно, например если мы пишем архиватор то алгоритмы архивации rar, zip, 7z... это стратегии, а выбирается нужная стратегия в зависимости от расширения файла.

TDrive ★★★★★ ()
Ответ на: комментарий от javaQest

а первый какой был?

Я не знаю какой был первый но точно помню тред про синглтон.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

От чего угодно, например если мы пишем архиватор то алгоритмы архивации rar, zip, 7z... это стратегии, а выбирается нужная стратегия в зависимости от расширения файла.

ну и зачем тут какая-то стратегия, если тут фактически, каждый класс и так обладает своим поведением? Что выбирать то? Привелди псевдокод какой-нибудь на свой пример.

javaQest ()
Ответ на: комментарий от TDrive

Ну, был про синглтон, я его понял, дальше был наблюдатель, я его тоже понял. Это третий. Больше я ни за что пока не брался. Так что не фантазируй.

javaQest ()
Ответ на: комментарий от TDrive

Вообще не приводи, я кажись понял о чем речь, щас попробую написать, а ты скажешь правильно я понял или нет.

javaQest ()
Ответ на: комментарий от TDrive
Decompress={
  decompress : function(){"default"},
  dispatch: function(arg){
     this[arg.replace(/.*\./, "")].decompress(arg)
  }
  // another behavor
}
Decompress.rar=Object.create(Decompress)
Decompress.zip=Object.create(Decompress)

with(Decompress){
  rar.decompress=function(archive){console.log("I decompress rar archive")}
  zip.decompress=function(archive){console.log("I decompress zip archive")}
}

with(Decompress) {
  dispatch("foo.rar") //I decompress rar archive
  dispatch("foo.zip") //I decompress zip archive
}

Я тут не стал делать zip и rar классами, так как нужды не вижу, но можно их и классами слелать, чтобы диспетчер возвращал их экземпляры с вызовом, а н просто вызывал decompress

Оно?

javaQest ()
Ответ на: комментарий от TDrive

Bот так вот изящней, полиморфизмом наружу:)

Decompress={
  decompress: function(arg){
     this[arg.replace(/.*\./, "")].decompress_(arg)
  }
  // another behavor
}
Decompress.rar=Object.create(Decompress)
Decompress.zip=Object.create(Decompress)

with(Decompress){
  rar.decompress_=function(archive){console.log("I decompress rar archive")}
  zip.decompress_=function(archive){console.log("I decompress zip archive")}
}

with(Decompress) {
  decompress("foo.rar") //I decompress rar archive
  decompress("foo.zip") //I decompress zip archive
}

javaQest ()
Ответ на: комментарий от javaQest

Нет не оно, у тебя нету четко заданного интерфейса для стратегий, у тебя нету контекста с помощью которого можно переключать эти стратегии,

this[arg.replace(/.*\./, "")].decompress_(arg)

это не входит в обязанности паттерна,
стратегия может быть сложной и описываться не одной функцией по этому

rar.decompress_=function(archive){console.log(«I decompress rar archive»)}

ни куда не годится.

TDrive ★★★★★ ()
Ответ на: комментарий от javaQest

Я тут не стал делать zip и rar классами, так как нужды не вижу, но можно их и классами слелать, чтобы диспетчер возвращал их экземпляры с вызовом, а н просто вызывал decompress

Смысл паттернов в принципе в том чтобы запилить один раз так что бы потом не пришлось перепиливать, по этому они должны быть классами, даже если в этом нет смысла сейчас он может появиться в будущем.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

у тебя нету четко заданного интерфейса для стратегий,

Это не важно, его допилить всегда можно, это сути дела не касается

у тебя нету контекста с помощью которого можно переключать эти стратегии,

контекстом переключения является расширение файла

стратегия может быть сложной и описываться не одной функцией по этому

Archiver={
  decompress: function(arg){
     this[arg.replace(/.*\./, "")].decompress_(arg)
  },
  compress: function(arg){
     this[arg.replace(/.*\./, "")].compress_(arg)
  }

  // another behavor
}
Archiver.rar=Object.create(Archiver)
Archiver.zip=Object.create(Archiver)

with(Archiver){
  rar.decompress_=function(archive){console.log("I decompress rar archive")}
  rar.compress_=function(archive){console.log("I compress rar archive")}
  zip.decompress_=function(archive){console.log("I decompress zip archive")}
  zip.compress_=function(archive){console.log("I compress zip archive")}
}

with(Archiver) {
  decompress("foo.rar")  //I decompress rar archive
  decompress("foo.zip")  //I decompress zip archive
  compress("foo.rar")    //I compress rar archive
  compress("foo.zip")    //I compress zip archive
}

вот тебе и Ынтерфейс, и много функций.

javaQest ()
Ответ на: комментарий от TDrive

Смысл паттернов в принципе в том чтобы запилить один раз так что бы потом не пришлось перепиливать, по этому они должны быть классами, даже если в этом нет смысла сейчас он может появиться в будущем.

Это оверхед по памяти, но я сказал, что это не проблема, и сути не касается. А вообще, в Ъ (в том чилсе и в руби, как не странно), перепилить экземпляры на классы как 2 пальца обоссать, на любом этапе разработки. Поэтому сомневаюсь, что это действительно «надо»

javaQest ()
Ответ на: комментарий от TDrive

Смысл паттернов в принципе в том чтобы запилить один раз так что бы потом не пришлось перепиливать, по этому они должны быть классами, даже если в этом нет смысла сейчас он может появиться в будущем.

Собственно, в JS ты и так любой объект можешь использовать в качестве класса.

javaQest ()
Ответ на: комментарий от javaQest

контекстом переключения является расширение файла

А потом ты решишь выбирать стратегию по первым байтам файла, а потом захочешь выбирать по первым байтам файла только в случае если не указано расширение файла, а потом подумаешь что надо бы проверять первые байты если неуказано расширение или если стратегия выбранная по расширению файла завершилась исключением, а потом ты поймеш что надо бы не все исключения ловить а только определенные, а потом решишь что неплохо бы пользователю дать возможность через флаг запуска указывать zip это или rar, и опапа в твоем паттерне стратегия уже половина программы, да и не паттерн это уже, а каша из кода.

  rar.decompress_=function(archive){console.log("I decompress rar archive")}
  rar.compress_=function(archive){console.log("I compress rar archive")}
  zip.decompress_=function(archive){console.log("I decompress zip archive")}
  zip.compress_=function(archive){console.log("I compress zip archive")}
инкапсуляцию потерял, rar должно быть отдельно, zip отдельно, и куда ты при такой структуре будешь пихать приватные методы отдельной стратегии?

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

Короче, контекст — это просто диспетчер, насколько я понял, он у меня неявно вшит в реализацию, можно его сделать и внешним, это роли не играет.

То есть, правильно я понял, что «стратегия» — это просто некие правила диспетчеризации, и к понятию «стратегия» как таковому это отношения не имеет?

javaQest ()
Ответ на: комментарий от TDrive

Эта вся твоя критика очень ценна для нас, но ты ушел далеко от темы. Все это делается, слова ради слов, не нужны, ближе к делу.

javaQest ()
Ответ на: комментарий от javaQest

Это оверхед по памяти, но я сказал, что это не проблема, и сути не касается. А вообще, в Ъ (в том чилсе и в руби, как не странно), перепилить экземпляры на классы как 2 пальца обоссать, на любом этапе разработки. Поэтому сомневаюсь, что это действительно «надо»

Если речь про дефолтную реализацию то надо, конкретные реализации любого паттерна могут немного отличаться, ясен пень их не стоит воспринимать буквально и свет клином на них не сошелся, но мы сейчас про «сферическую стратегию в вакууме»

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

инкапсуляцию потерял, rar должно быть отдельно, zip отдельно, и куда ты при такой структуре будешь пихать приватные методы отдельной стратегии?

Ты кстати, вроде на руби пишешь, а рассуждаешь как жаба-лалка. Кому как не рубисту знать, что в Ъ инкапсуляция к этим быдлопонятиям отношения не имеет. Объект(актор) инкапсулирует поведение, в этом суть инкапсуляции, а не в твоих ко-ко-ко

javaQest ()
Ответ на: комментарий от javaQest

Короче, контекст — это просто диспетчер, насколько я понял, он у меня неявно вшит в реализацию, можно его сделать и внешним, это роли не играет.

Если он вшит это один паттерн, называется анонiмусо_стратегия, со своими плюсами и минусами, пример минуса анонiмусо_стратегия я привел, если он внешний, а точнее вообще ни как не связан это другой паттен, называется стратегия.

То есть, правильно я понял, что «стратегия» — это просто некие правила диспетчеризации, и к понятию «стратегия» как таковому это отношения не имеет?

Ты в принципе не понимаешь, что такое паттерны и для чего они нужны. В паттернах главное не то что они делают а то как они это делают, их структура, потому что благодаря хорошей структуре паттерна достигается удобство разработки и сопровождения кода. Можно придумать тысячи способов реализации одной и той же фичи и только 5-10 из них не будут write-only вот эти 5-10 и становятся паттернами.

TDrive ★★★★★ ()
Ответ на: комментарий от javaQest

Эта вся твоя критика очень ценна для нас, но ты ушел далеко от темы. Все это делается, слова ради слов, не нужны, ближе к делу.

думаю я тебе выше ответил.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

И, кстати, тот пример, который из википедии, никакого отношения к тому что ты мне объяснил, отношения не имеет. Там де факто, несмотря на кружева, в итоге просто тупо вызываются 3 функции.

А за объяснение спасибо. Я понял смысл. Конкретная реализация не столь важна. Это все по сути, сводится к диспетчеризации по каким-либо признакам.

javaQest ()
Ответ на: комментарий от javaQest

Ты кстати, вроде на руби пишешь, а рассуждаешь как жаба-лалка. Кому как не рубисту знать, что в Ъ инкапсуляция к этим быдлопонятиям отношения не имеет. Объект(актор) инкапсулирует поведение, в этом суть инкапсуляции, а не в твоих ко-ко-ко

хорошо это не приватный метод, это сервисный метод или вообще сервисный класс который нужен только одной стратегии, куда ты его засунешь?

TDrive ★★★★★ ()
Ответ на: комментарий от javaQest

И, кстати, тот пример, который из википедии, никакого отношения к тому что ты мне объяснил, отношения не имеет. Там де факто, несмотря на кружева, в итоге просто тупо вызываются 3 функции.

Нет там как раз все правильно

var showInWindowStatus = new Context( new StrategyWindowStatus() );
var showInNewWindow = new Context( new StrategyNewWindow() );
var showInAlert = new Context( new StrategyAlert() );
3 разных контекста, включаются одновременно без каких либо условий.

А за объяснение спасибо. Я понял смысл. Конкретная реализация не столь важна. Это все по сути, сводится к диспетчеризации по каким-либо признакам.

Вообщето конкретная реализация == паттерн, просто если идет речь о производительности и тд естественно ни кто не будет смотреть на чистоту этого паттерна.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

хорошо это не приватный метод, это сервисный метод или вообще сервисный класс который нужен только одной стратегии, куда ты его засунешь?

Засуну, уж куда-нибудь, не переживай. Оверинжиниринг мне не нужен. Я буду плясать от задачи. Если нужно расширять, буду рефакторить. Сразу учитывать в реализации все возможные варианты — это путь в никуда.

javaQest ()
Ответ на: комментарий от TDrive

Нет там как раз все правильно

Что ты несешь? Ты что не понимаешь, что вот этот вот код

function Context(strategy) {
		this.exec = function(message) {
			strategy.exec(message);
		};
	}
там ничего вообще не делает? Это называется тавтология.

javaQest ()

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

function quack() { console.log('quack'); }
function bark() { console.log('bark'); }
function meow() { console.log('meow'); }

function Speaker() {
    this._type = 'dog';
    this._speakStrategy = bark;
}

Speaker.prototype.setType = function (type) {
  this._type = type;
  switch (type) {
    case 'duck':
      this._speakStrategy = quack;
      break;
    case 'dog':
      this._speakStrategy = bark;
      break;
    case 'cat':
      this._speakStrategy = meow;
      break;
  }
};

Speaker.prototype.speak = function () {
  this._speakStrategy();
};

но если поведение сложное и связано с несколькими функциями, можно и иерархию классов сделать.

Legioner ★★★★★ ()
Ответ на: комментарий от javaQest

Засуну, уж куда-нибудь, не переживай. Оверинжиниринг мне не нужен. Я буду плясать от задачи. Если нужно расширять, буду рефакторить. Сразу учитывать в реализации все возможные варианты — это путь в никуда.

Вот как раз рефакторить постоянно это конечно путь кудато но очень доооолгий, а паттерны нужны что бы решить эту проблему.

Оверинжиниринг мне не нужен

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

TDrive ★★★★★ ()
Ответ на: комментарий от javaQest

Он и не должен ничего делать, это интерфейс. достаточно того что он есть и четко определен.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

это интерфейс. достаточно того что он есть и четко определен.

Зачем он там нужен?

javaQest ()
Ответ на: комментарий от javaQest

Я перепутал, это не интерфейс а контекст, он отвечает за логику переключения стратегий, не выбора определеной стратегии а логику их переключения.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

Это дерьмо, играет там примерно такую же роль как

fu=function(){return "foo"}
theFu=function(fu){return fu()}

theFu(fu)
надеюсь, доступно объяснил.

javaQest ()
Ответ на: комментарий от Legioner

логика выбора конкретной стратегии не входит в паттерн стратегия.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

У него «логика переключений» что взял, то отдал. Только через жопу создание объекта.

javaQest ()
Ответ на: комментарий от javaQest

Нет это дерьмо берет на себя вполне определенную обязанность, «логика переключения стратегий», а 1 там строчка или 51 это не важно.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

Нет это дерьмо берет на себя вполне определенную обязанность, «логика переключения стратегий», а 1 там строчка или 51 это не важно.

Но оно там ничего не переключает, какая логика, о чем ты говоришь?

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

javaQest ()
Ответ на: комментарий от javaQest

вообщето он и возвращает класс со своим поведением

var showInWindowStatus = new Context( new StrategyWindowStatus() );

TDrive ★★★★★ ()
Ответ на: комментарий от javaQest

Просто там частный случай когда контекст ничего не делает, а если вернуться к нашему примеру с архиваторами в роле контекста мог бы быть класс архиватор, а zip это или rar архиватор будет определяться переданной ему стратегией при создании экземпляра.

TDrive ★★★★★ ()
Ответ на: комментарий от Legioner

Спасибо, ясно.

Хотя, это можно было бы проще написать

Animal=function(sound){ this.sound=sound }
Animal.prototype.say=function(){console.log(this.sound)}

dog=new Animal("bark")
cat=new Animal("meow")
duck=new Animal("quack")


with(Speacker=function(){}){
 prototype.setType=function(object){
  this.type=object
 }
 prototype.speack=function(){this.type.say()}
}

javaQest ()
Ответ на: комментарий от TDrive

он и возвращает класс со своим поведением

он экземпляр, кстати возвращает, а не класс.

javaQest ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.