示例类图想象一下媒体播放器。大多数媒体播放器都有一个播放按钮 - 当我们激活它时,它通常会改变它的外观并变成一个暂停按钮。现在单击暂停按钮也可以执行不同的操作 - 它会暂停播放并恢复播放按钮。这是状态设计模式的一个很好的候选者,根据玩家所处的状态,会发生不同的动作。
下面的类图显示了为播放和暂停按钮实现此功能所需的类:我们的播放和暂停实现将状态设置为相反的状态并使我们的播放器正常运行。使用状态设计模式也使我们的代码更加优雅 - 当然,我们可以使用if语句并根据值执行不同的操作。但是,当有许多州时,它很容易失控。
代码示例让我们看一下之前显示的类图的代码。首先,让我们看看State trait:
trait State [T] {def press(context:T)}
它非常简单,允许扩展类实现press方法。根据我们的类图,我们有两个实现:我们使它们变得简单,它们只打印相关的消息,然后将当前状态更改为相反的状态。
我们的模型定义了一个MediaPlayer类,如下所示:
case class MediaPlayer() {
private var state: State[MediaPlayer] = new Paused
def pressPlayOrPauseButton(): Unit = {
state.press(this)
}
def setState(state: State[MediaPlayer]): Unit = {
this.state = state
}
}
trait State[T] {
def press(context: T)
}
class Playing extends State[MediaPlayer] {
override def press(context: MediaPlayer): Unit = {
System.out.println("Pressing pause.")
context.setState(new Paused)
}
}
class Paused extends State[MediaPlayer] {
override def press(context: MediaPlayer): Unit = {
System.out.println("Pressing play.")
context.setState(new Playing)
}
}
object MediaPlayerExample {
def main(args: Array[String]): Unit = {
val player = MediaPlayer()
player.pressPlayOrPauseButton()
player.pressPlayOrPauseButton()
player.pressPlayOrPauseButton()
player.pressPlayOrPauseButton()
}
}
输出结果如下:
正如您在示例输出中看到的那样,按下每个按钮时状态会发生变化,并执行不同的操作,我们使用不同的打印消息进行了说明。
对我们的应用程序的可能改进将涉及使状态对象单体。 正如您所看到的,它们始终是相同的,因此实际上不需要每次都创建新的。
有什么好处状态设计模式对于使代码可读和摆脱条件语句非常有用。
对于州设计模式来说不是很好,没有什么大的缺点。 开发人员应该注意的一件事是由对象状态的变化引起的副作用。
正如您在示例输出中看到的那样,按下每个按钮时状态会发生变化,并执行不同的操作,我们使用不同的打印消息进行了说明。
对我们的应用程序的可能改进将涉及使状态对象单体。正如您所看到的,它们始终是相同的,因此实际上不需要每次都创建新的。
有什么好处状态设计模式对于使代码可读和摆脱条件语句非常有用。
对于状态设计模式来说不是很好,没有什么大的缺点。开发人员应该注意的一件事是由对象状态的变化引起的副作用。