sábado, 28 de agosto de 2010

Design Patterns em Scala: Strategy

Strategy é um dos padrões mais legais na minha opinião, juntamente com Template Method, Command, Observer, entre outros. Com Scala dá pra implementar o Strategy com pelo menos duas maneiras diferentes: O comum, extendendo um Trait com a interface da estratégia/algoritmo, ou então utilizando o objeto método como sendo um algoritmo. Já que em Scala (assim como em outras linguagens inteiramente OO) o método é um objeto, isto é, podemos chamar métodos de um método, podemos passar métodos como parâmetros, etc, não há a necessidade de encapsularmos um algoritmo dentro de uma classe. Segue as duas versões: Encapsulando o algoritmo em objetos: Strategy.scala package scala.behavioral // Strategy = Policy // Encapsular um algoritmo para que ele possa ser alterado dinamicamente // Abstract Implementation trait Strategy {  def run() { // Template method for legibility   algorithm()  }  def algorithm() } // Concrete Implementation class DefaulStrategy extends Strategy {  override def algorithm() {   println("default algorithm")  } } class StrategyA extends Strategy {  override def algorithm() {   println("solved using algorithm A")  } } class StrategyB extends Strategy {  override def algorithm() {   println("solved using algorithm B")  } } class MyApplication(var strategy:Strategy) {  def doSomething() {   strategy.run()  } } // Client object StrategyClient extends Application {  var arg = "a"  var strategy:Strategy = _  arg match {   case "a" => strategy = new StrategyA()   case "b" => strategy = new StrategyB()   case _ => strategy = new DefaulStrategy()  }  var myapp = new MyApplication(strategy)  myapp.doSomething()  myapp.strategy = new StrategyB()  myapp.doSomething() } Utilizando o próprio objeto método: Strategy2.scala package scala.behavioral // Strategy = Policy // Encapsular um algoritmo para que ele possa ser alterado dinamicamente // Example with function-objects // Concrete Implementation class SomeParam class SomeReturnValue object Strategies {  def strategyA(param:SomeParam) : SomeReturnValue = {   println("strategy A")   return new SomeReturnValue()  }  def strategyB(param:SomeParam) : SomeReturnValue = {   println("strategy B")   return new SomeReturnValue()  }  def strategyC(param:SomeParam) : SomeReturnValue = {   println("strategy C")   return new SomeReturnValue()  } } class MyApplication2(var strategy: (SomeParam => SomeReturnValue)) {  def doSomething(param:SomeParam) : SomeReturnValue = {   return strategy(param)  } } // Client object StrategyClient2 extends Application {  var arg = "a"  var strategy:(SomeParam => SomeReturnValue) = _  arg match {   case "a" => strategy = Strategies.strategyA   case "b" => strategy = Strategies.strategyB   case _ => strategy = Strategies.strategyC  }  var myapp = new MyApplication2(strategy)  myapp.doSomething(new SomeParam())  myapp.strategy = Strategies.strategyC  myapp.doSomething(new SomeParam()) }

Nenhum comentário:

Postar um comentário