デザインパターン:Strategy Pattern

Java

このパターンが威力を発揮するのはこういったケース。

ある決まった特定の振る舞いを持つが、その振る舞いのバリエーションが多様な場合。

は?ですね。

例を挙げて説明してみます。

特定の振る舞い「業務の種類・業務場所・業務権限」を、全社員は持っているとします。

クラス図にするとこんな感じ。

で、エンジニア職の人は「システムを作る」業務を、営業職の人は「ものを売る」業務をさせます。

クラス図にするとこんな感じ。

少し複雑にしてみましょう。

A部署で働く社員は、「セントラルホール」で業務をしてもらい、

B部署で働く社員は「駅近のビル」で業務をしてもらいます。

クラス図にするとこんな感じですかね。

さらに複雑にします。

社員の中で、管理職の人には、「管理者権限」を与え、平社員の人は「権限なし」とします。

はい、ややこしい。笑

※もちろん、他にもっと良い実装方法はありますが今回はStrategyPatternの説明のため、あえてこんな感じでクラスを増やしていってます。

ここに、例えば課長クラスが入ってきて、A部署の課長は「東京オフィス」で働いてもらって、B部署の課長には「大阪オフィス」で働いてもらう

なんてのが追加されれば、どうだろうか。。。パニックですね

これを綺麗さっぱりサクッとお手軽に解決してくれるのがStrategyPatternです!

こうなります!

業務内容を表す「I_Work」インターフェースを実装した「DoWork_As_Engineer」と「DoWork_As_SalesMan」それぞれに具体的な処理内容を記載しています。

同様に、業務場所を表す「I_WorkPlace」、権限を表す「I_Authorization」それぞれ実装した具象クラスで具体的な処理内容を記載。

ミソなのが、「Worker」クラスです。

こいつは、コンストラクタで、インターフェースを実装した具象クラスのインスタンスを受け取り、Workerクラスがもつフィールドに格納します。

で、Workerクラス自身にもdoWork、workPlace、authorizeメソッドを持たせ、その処理の中でフィールドを使用してコンストラクタで格納した具象クラスの具象メソッドを呼びます。

実際のコードがこれです。

public class Worker {
	private I_DoWork work;
	private I_WorkPlace place;
	private I_Authorization auth;

	public Worker(I_DoWork work, I_WorkPlace place, I_Authorization auth) {
		this.work = work;
		this.place = place;
		this.auth = auth;
	}

	public void doWork() {
		this.work.doWork();;
	}
	public void workPlace() {
		this.place.workPlace();
	}
	public void authorize() {
		this.auth.authorize();
	}
}

各インターフェースのコードはこれ。

public interface I_DoWork {
	void doWork();
}
public interface I_WorkPlace {
	void workPlace();
}
public interface I_Authorization {
	void authorize();
}

具象クラスのコードはこれ。

public class DoWork_As_Engineer implements I_DoWork{
	@Override
	public void doWork() {
		System.out.println("Make Some System!");
	}
}
public class DoWork_As_SalesMan implements I_DoWork{
	@Override
	public void doWork() {
		System.out.println("Sell some resources!");
	}
}
public class WorkPlace_As_Central implements I_WorkPlace{
	@Override
	public void workPlace() {
		System.out.println("Work in Central Hall");
	}
}
public class WorkPlace_As_Building implements I_WorkPlace{
	@Override
	public void workPlace() {
		System.out.println("Work in a building near a station");
	}
}
public class Authorization_As_Employee implements I_Authorization{
	@Override
	public void authorize() {
		System.out.println("No Right has been assigned!");
	}
}
public class Authorization_As_Manager implements I_Authorization{
	@Override
	public void authorize() {
		System.out.println("Management Right has been assigned!");
	}
}

では、実際に使ってみます。A部署で働く平社員のエンジニアを作ってみます。

Worker engineer_depA = new Worker(
new DoWork_As_Engineer(),
new WorkPlace_As_Central(),
new Authorization_As_Employee());

engineer_depA.doWork();
engineer_depA.workPlace();
engineer_depA.authorize();

インスタンス化時にコンストラクタに「エンジニア職、セントラルホール、権限なし」の具象クラスをインスタンス化して渡しています。

Workerクラスでは、これらをインターフェースとして受け取っているので、具象クラスがそのインターフェースを実装したものである限り、振る舞いを意識せずに受け取ることができると言うわけです。俗に言う、ポリモーフィズムですね

実行結果はこれ

Make Some System!
Work in Central Hall
No Right has been assigned!

予想通りですね。

てな、感じで、振る舞いは決まっているがその振る舞いのパターンが多様な場合にこのデザインパターンは有効です。

是非とも活用してくださいませ!

では!

タイトルとURLをコピーしました