[iOS 8] Swiftでデザインパターン No.9 State

2014.11.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

State

State とは

英単語 State には以下のような意味があります。

  • 状態
  • 状況

State パターンは、オブジェクトの内部状態が変化したときに、オブジェクトが振る舞いを変えるようにするパターンです。

クラス図

state

ポイント

  • Context は状態を表す状態オブジェクトを保持している
  • 状態に依存した要求はすべてこの状態オブジェクトに委譲する

サンプルコード

例として、信号機を考えます。

信号機には以下の 3 つの状態が存在します。

本来、信号機は時間が経つにつれて状態を変化させますが、自動ではつまらないため、画面上のボタンがタップされたら状態を変化し、その状態の時の色を背景色にするというコードを書いてみました。

実行画面

TrafficLight

class TrafficLight {

private var currentState: State = StateGreen()

var state: State {
get {
return currentState
}
set {
currentState = newValue
}
}

var color: UIColor {
get {
return currentState.color
}
}

func changeColor() {
currentState.goNext(self)
}
}

信号機を表すクラスです。

状態を表すオブジェクト currentState を保持します。 色を取得する処理や状態を変更する処理は、状態オブジェクトに委譲しています。

State

class State {

var color: UIColor {
get {
return UIColor.blackColor()
}
}

func goNext(trafficLight: TrafficLight) {}
}

状態を表す抽象クラスです。

StateGreen

class StateGreen: State {

override var color: UIColor {
get {
return UIColor.greenColor()
}
}

override func goNext(trafficLight: TrafficLight) {
trafficLight.state = StateYellow()
}
}

「青」状態を表すクラスです。

次の状態は「黄」です。

StateYellow

class StateYellow: State {

override var color: UIColor {
get {
return UIColor.yellowColor()
}
}

override func goNext(trafficLight: TrafficLight) {
trafficLight.state = StateRed()
}
}

「黄」状態を表すクラスです。

次の状態は「赤」です。

StateRed

class StateRed: State {

override var color: UIColor {
get {
return UIColor.redColor()
}
}

override func goNext(trafficLight: TrafficLight) {
trafficLight.state = StateGreen()
}
}

「赤」状態を表すクラスです。

次の状態は「青」です。

ViewController

class ViewController: UIViewController {

let trafficLight = TrafficLight()

override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = trafficLight.color
}

@IBAction func buttonTapped(sender: AnyObject) {
trafficLight.changeColor()
view.backgroundColor = trafficLight.color
}
}

ビューコントローラです。

ボタンがタップされた時に信号機の状態を変化させ、その時の色を背景色に設定しています。

まとめ

  • Swift のセッターは引数を省略することができる
  • その場合、値は newValue という変数に格納される

リンク

おまけ

Q. 信号の緑は青色に見えますが、青と緑、どっちが正しいんですか?

A.

昭和5年に初めて信号機がついたとき、法令上は「緑色」でした。 しかし、日本語の「青」の範囲は広く、青菜や青物など緑色のものを「青」と呼ぶ場合が多く、色の三原色「赤・黄・青」からも緑色の信号も青信号と呼ばれたのでしょう。 こうして青色信号という呼び名が一般的になってきたことから、昭和22年に法令でも青信号と呼ぶようになり、昭和48年以降に作られた信号機は呼び名どおり青色になりました。 (それ以前に作られた信号機は緑色に見えるものがあります) このようなことから、今では一般的に信号機は「赤・黄・青」と呼ぶようになったのです。

警視庁ホームページ 広報けいしちょう より


開発でもよくあるのですが、名前が複雑だったり分かりづらかったりすると認識合わせに時間がかかったりします。 また、名前の変更を中盤〜終盤で行おうとすると、結構なコストがかかってしまうものです。 というわけで、何かに名前をつけるときはじっくり考えて適切な名前を付けるようにしましょう。 名前は重要!