1. 概要(Overview)
Hide Delegate は、あるクラスが他のクラスを利用する際に、委譲(delegation)の存在を隠して直接依存させない ようにするリファクタリングです。
クライアントコードが「どのオブジェクトにアクセスするか」を意識しなくてもよいように、窓口メソッドを提供して依存関係をシンプルにします。
目的は以下の通りです:
- クライアントを中間クラスに依存させることで、変更の影響を局所化する
- カプセル化を強化し、意図を分かりやすくする
2. 適用シーン(When to Use)
- クライアントコードが、オブジェクトの内部構造を知りすぎている
- クライアントが「委譲先のクラスのメソッド」を直接呼び出している
- 内部構造が変わると、複数の呼び出し元を修正する必要がある
よくある匂い:
- Message Chains(メッセージチェーン)
- Inappropriate Intimacy(不適切な親密さ)
3. 手順(Mechanics / Steps)
- クライアントが委譲先に直接アクセスしている箇所を確認
- 元クラスに委譲先メソッドをラップする「窓口メソッド」を追加
- クライアントコードを修正し、窓口メソッドを利用するように変更
- クライアントから委譲先への直接アクセスを削除
4. Kotlin 例(Before → After)
Before:クライアントが内部構造を知りすぎている
class Department(val manager: Person)
class Person(val name: String)
fun printManager(department: Department) {
// クライアントが「Department → Manager → name」と内部構造を知っている
println(department.manager.name)
}
- クライアントが
Departmentの内部構造に依存 -
Departmentクラスが変わると、クライアントコードを修正する必要が出る
After:委譲を隠す
class Department(private val manager: Person) {
fun getManagerName(): String = manager.name
}
class Person(val name: String)
fun printManager(department: Department) {
// ✅ クライアントは内部構造を知らなくても良い
println(department.getManagerName())
}
→ クライアントは manager という存在を知らなくてもよい。
→ 内部構造が変わっても 変更影響が Department に閉じる。
5. 効果(Benefits)
- クライアントが内部構造に依存しなくなる → 変更に強い設計
- 委譲を隠すことで カプセル化が強化
- クラスの責務が明確になり、クライアントコードが読みやすくなる
6. 注意点(Pitfalls)
- 委譲メソッドが増えすぎると、Middle Man(仲介人)問題 を引き起こす
- すべてを隠すのではなく、本当に変更に弱い部分だけ隠す のが良い
- クラスの API が肥大化しすぎないように注意
まとめ
- Hide Delegate は「委譲先をクライアントに意識させない」リファクタリング
- 判断基準:クライアントが委譲先を知る必要があるか?
- 基本思想:依存を減らし、変更の影響を局所化する