0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【リファクタリング】Replace Type Code with State/Strategy (型コードを State/Strategy に置き換える)

Posted at

1. 概要(Overview)

Replace Type Code with State/Strategy は、型コードや分岐処理を、
State パターンStrategy パターン を使って置き換えるリファクタリングです。

「型コードごとに異なる振る舞い」を

  • State パターン:オブジェクトの状態ごとに振る舞いを変える
  • Strategy パターン:アルゴリズムや処理方法を差し替える

といった仕組みによって表現します。

目的

  • 分岐処理を排除して ポリモーフィズム に置き換える
  • 状態遷移やアルゴリズム切り替えを 動的に差し替え可能 にする
  • コードを拡張可能(OCP: 開放閉鎖原則)に保つ

2. 適用シーン(When to Use)

  • 型コードやフラグに応じて when / if 文で分岐している
  • 「種類」や「状態」に応じた 異なるアルゴリズム を使いたい
  • 状態遷移や戦略切り替えが頻繁に起こる
  • サブクラス化(Replace Type Code with Subclasses)では柔軟さが足りない場合

よくある匂い:

  • Type Code(型コード)
  • Switch Statements(スイッチ文)
  • Divergent Change(散漫な変更)

3. 手順(Mechanics / Steps)

  1. 型コードを使って分岐している処理を特定
  2. 抽象クラス/インターフェースを導入し、共通メソッドを定義
  3. 型コードごとに State/Strategy 実装クラスを作成
  4. 元クラスは型コードではなく State/Strategy オブジェクト を保持
  5. 分岐処理を削除し、ポリモーフィズムに移す

4. Kotlin 例(Before → After)

Before:型コードによる分岐

class Employee(val name: String, val type: Int) {
    companion object {
        const val ENGINEER = 0
        const val MANAGER = 1
        const val SALESMAN = 2
    }

    fun payAmount(): Int {
        return when (type) {
            ENGINEER -> 3000
            MANAGER -> 5000
            SALESMAN -> 2000
            else -> throw IllegalArgumentException("Unknown type")
        }
    }
}
  • type に応じて when で分岐
  • 新しい種類を追加すると when を修正する必要あり

After①:Strategy パターンに置き換え

interface PaymentStrategy {
    fun payAmount(): Int
}

class EngineerPayment : PaymentStrategy {
    override fun payAmount() = 3000
}

class ManagerPayment : PaymentStrategy {
    override fun payAmount() = 5000
}

class SalesmanPayment : PaymentStrategy {
    override fun payAmount() = 2000
}

class Employee(val name: String, private val strategy: PaymentStrategy) {
    fun payAmount(): Int = strategy.payAmount()
}

fun main() {
    val alice = Employee("Alice", EngineerPayment())
    val bob = Employee("Bob", ManagerPayment())

    println("${alice.name} earns ${alice.payAmount()}")
    println("${bob.name} earns ${bob.payAmount()}")
}
  • when が消え、戦略オブジェクトの差し替えで動作が変わる

5. 効果(Benefits)

  • if/when を削除 → コードがシンプルに
  • 状態や戦略を 動的に切り替え可能
  • 新しい戦略/状態を追加しても既存コードに影響しない(OCP に適合)
  • テスト容易性向上(戦略や状態を差し替えて単体テスト可能)

6. 注意点(Pitfalls)

  • クラスが増えるため、小規模な処理では冗長になる
  • 状態遷移が複雑になる場合、状態遷移図の設計が必要
  • Strategy は「外から差し替え」、State は「内部で遷移」する、という違いを意識すること

まとめ

  • Replace Type Code with State/Strategy は「型コードや分岐」を ポリモーフィズム に置き換えるリファクタリング
  • Strategy:アルゴリズムの差し替えに適用
  • State:オブジェクトの状態遷移に適用
  • 基本思想:型コードを消して、オブジェクトの振る舞いで表現する

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?