将有状态的类变为无状态

时间:2016-03-31 07:17:53

标签: scala

这是一个有状态的类,但是它表示类在scala中应该是无状态的,而有状态对象在多线程环境中可能会出错。那么有人可以帮助将其转变为无国籍阶层吗?

trait SwitchStrategy {
  def shouldSwitch: Boolean
}

object Strategies {

  def countdown(counts: Int): SwitchStrategy = {
    return new SwitchStrategy {
      private[this] var count = 0

      override def shouldSwitch: Boolean = {
        count += 1
        return if (count >= counts) {
          count = 0;
          true
        } else false
      }
    }
  }
}

3 个答案:

答案 0 :(得分:2)

你的整个问题都是建立在保持状态的基础之上,并且没有“魔法语法”#34;消除它。方法yast不是引用透明的:

shouldSwitch

如果你想使用功能范例,采用使用可变状态并重写的命令式解决方案并不是一个好方法。我不知道你的程序的外部细节,所以我真的无法改变它。您显然需要做的第一件事是删除val s = Strategies.countdown(3) println(s.shouldSwitch) // false println(s.shouldSwitch) // false println(s.shouldSwitch) // true 所依赖的可变状态。一个常见的解决方案是将调度程序的状态信息提供给负责人,这在这种情况下意味着SwitchStrategy的调用提供了计数。

答案 1 :(得分:1)

处理状态的全功能方法称为状态monad。

此处提供了更多信息:http://eed3si9n.com/learning-scalaz/State.html或此处:http://timperrett.com/2013/11/25/understanding-state-monad/

没有语法或简单的重构可以让您从一种风格转换到另一种风格。

简单来说:

为了达到预期的结果,而不是修改内部状态,每个操作都应返回一对(Result, NewState),并且在连续操作中,您应该丢弃先前的状态并使用新返回的状态。

答案 2 :(得分:1)

(可变)国家总是不好,有时是不可避免的。迭代器具有状态,I / O流也是如此...尝试在没有它们的情况下编写有用的东西。 它也不一定会在多线程环境中出错。" ...尤其是,如果你不在线程之间分享你的州长。

话虽如此,无状态(或相当引用透明)代码更容易推理,因此往往更可靠和更健壮。所以,当你可以绕过"天真的"要求拥有国家,通常是一个好主意。

在这种情况下,我认为,这样的事情可能有用:

   trait SwitchStrategy { 
      def shouldSwitch: Boolean
      def next: SwitchStrategy        


      @tailrec
      final def apply[T](strategy: T => T)(initial: T): T = 
        if(shouldSwitch) initial else next(strategy)(strategy(initial))
   }   

   case class CountDown(n: Int) extends SwitchStrategy {
      def next = n match {
         case 0 => this
         case _ => copy(n-1)
      }
      def shouldSwitch = n == 0
   }

然后您可以像这样使用它:

   def makeZero = CountDown(10) { n:Int => n - 1 } (10)
   def plus(a: Int, b: Int) = CountDown(a) { n: Int => n + 1} (b)
   def pow(a: Int, b: Int) = CountDown(b-1) { n: Long => n * a } (a)