委譲されるクラスは委譲したクラスが隠蔽する
(一番進捗が出ているタスク, 一番進捗が出ていないタスク void → int)
設計
- 顧客 | マネージャー、エンジニア1、 エンジニア2
- が居るとする
- 顧客は知りたい
- エンジニア1、エンジニア2 が進めるタスクの内
- 一番進捗が出ているタスク
- 一番進捗が出ていないタスク
この時、どうシステム設計するのが良いか
A plan
「顧客がマネージャーに
『一番進捗が出ているタスク、一番進捗が出ているタスク』
を尋ねて、結果を教えてもらう」
B plan
「顧客が エンジニア1, エンジニア2 に進捗率を尋ね
『一番進捗が出ているタスク、一番進捗が出ているタスク』を弾き出す」
A plan の方が良い
少なくとも顧客の立場からしたら B plan は面倒だし不自然
実装
マネージャー, エンジニア1, エンジニア2 間で委譲を使う
src | +-- jp.ymatsukawa +-- Main.java | +-- delegation | + -- Manager.java + -- Engineer.java
jp.ymatsukawa/Main.java
package jp.ymatsukawa; import jp.ymatsukawa.delegation.Manager; public class Main { public static void main(String[] args) { Manager BPManager = new Manager(); System.out.println(BPManager.getLeastProgressedTaskPercentage()); System.out.println(BPManager.getMostProgressedTaskPercentage()); } }
System out
30 80
jp.ymatsukawa/delegation/Manager.java
package jp.ymatsukawa.delegation; public class Manager { private Engineer inexperiencedEngineer = new Engineer(30); private Engineer veteranEngineer = new Engineer(80); public int getMostProgressedTaskPercentage() { return Math.max(this.inexperiencedEngineer.getProgress(), this.veteranEngineer.getProgress()); } public int getLeastProgressedTaskPercentage() { return Math.min(this.inexperiencedEngineer.getProgress(), this.veteranEngineer.getProgress()); } }
jp.ymatsukawa/delegation/Engineer.java
package jp.ymatsukawa.delegation; class Engineer { private int taskProgress; protected Engineer(int taskProgress) { this.taskProgress = taskProgress; } public int getProgress() { return this.taskProgress; } }
委譲されるクラスを隠蔽する目的
クライアントと委譲されるクラスの密結合を回避するため
- 委譲フィールドを公開すると
- B plan が発生し得る
- App class と Engineer class が互いに密結合になる
- Manager class が Engineer class の作業範囲を公開するだけの class になりうる
委譲フィールド公開版(極例)
src | +-- jp.ymatsukawa +-- Main.java | +-- delegation | + -- Manager.java + -- Engineer.java
jp.ymatsukawa/Main.java
package jp.ymatsukawa; import jp.ymatsukawa.delegation.Manager; public class Main { public static void main(String[] args) { Manager BPManager = new Manager(); int engineer1Progress = BPManager.getInexperiencedEngineer().getProgress(); int engineer2Progress = BPManager.getVeteranEngineer().getProgress(); System.out.println(Math.min(engineer1Progress, engineer2Progress)); System.out.println(Math.max(engineer1Progress, engineer2Progress)); } }
System out
30 80
jp.ymatsukawa/delegation/Manager.java
package jp.ymatsukawa.delegation; public class Manager { private Engineer inexperiencedEngineer = new Engineer(30); private Engineer veteranEngineer = new Engineer(80); public Engineer getInexperiencedEngineer() { return this.inexperiencedEngineer; } public Engineer getVeteranEngineer() { return this.veteranEngineer; } }
jp.ymatsukawa/delegation/Engineer.java
package jp.ymatsukawa.delegation; class Engineer { private int taskProgress; protected Engineer(int taskProgress) { this.taskProgress = taskProgress; } public int getProgress() { return this.taskProgress; } }
蛇足
私の Java 委譲に対する現状認識
「作業を別クラスに任せること。公開度は自クラスまで(委譲フィールドは含めない)」