Javaにおけるステートデザインパターン

状態デザインパターンは、行動デザインパターンの一つです。状態デザインパターンは、オブジェクトが内部の状態に基づいてその動作を変更する場合に使用されます。

状態デザインパターン

オブジェクトの動作を状態に基づいて変更する必要がある場合、オブジェクトに状態変数を持つことができます。その後、if-elseの条件ブロックを使用して、状態に基づいて異なるアクションを実行します。状態デザインパターンは、ContextStateの実装を介して、これを実現するための体系的で緩やかに結合された方法を提供するために使用されます。状態パターンContextは、Stateの具体的な実装の1つに対するState参照を持つクラスです。Contextはリクエストを状態オブジェクトに転送して処理します。簡単な例でこれを理解しましょう。TVのリモコンを実装する場合、単純なボタンでアクションを実行するとします。状態がONの場合、TVをオンにし、状態がOFFの場合、TVをオフにします。次のように、if-elseの条件を使用して実装することができます。 TVRemoteBasic.java

package com.journaldev.design.state;

public class TVRemoteBasic {

	private String state="";
	
	public void setState(String state){
		this.state=state;
	}
	
	public void doAction(){
		if(state.equalsIgnoreCase("ON")){
			System.out.println("TV is turned ON");
		}else if(state.equalsIgnoreCase("OFF")){
			System.out.println("TV is turned OFF");
		}
	}

	public static void main(String args[]){
		TVRemoteBasic remote = new TVRemoteBasic();
		
		remote.setState("ON");
		remote.doAction();
		
		remote.setState("OFF");
		remote.doAction();
	}

}

クライアントコードは、リモートの状態を設定するために使用する特定の値を知っている必要があります。さらに、状態の数が増えると、実装とクライアントコードの間の強い結合は非常に維持および拡張が困難になります。これから、上記のテレビリモートの例を実装するために、Stateパターンを使用します。

Stateデザインパターンのインターフェース

まず、異なる具体的な状態とコンテキストクラスによって実装されるべきメソッドを定義するStateインターフェースを作成します。State.java

package com.journaldev.design.state;

public interface State {

	public void doAction();
}

Stateデザインパターンの具体的な状態の実装

この例では、テレビをオンにするための状態とオフにするための状態の2つの状態があります。したがって、これらの動作のための2つの具体的な状態の実装を作成します。TVStartState.java

package com.journaldev.design.state;

public class TVStartState implements State {

	@Override
	public void doAction() {
		System.out.println("TV is turned ON");
	}

}

TVStopState.java

package com.journaldev.design.state;

public class TVStopState implements State {

	@Override
	public void doAction() {
		System.out.println("TV is turned OFF");
	}

}

これで、内部の状態に基づいて動作を変更するContextオブジェクトを実装する準備が整いました。

State Design Pattern Context Implementation

TVContext.java

package com.journaldev.design.state;

public class TVContext implements State {

	private State tvState;

	public void setState(State state) {
		this.tvState=state;
	}

	public State getState() {
		return this.tvState;
	}

	@Override
	public void doAction() {
		this.tvState.doAction();
	}

}

コンテキストもStateを実装し、現在の状態への参照を保持し、リクエストを状態の実装に転送します。

State Design Pattern Test Program

これで、TVリモートの状態パターンの実装をテストする単純なプログラムを作成しましょう。TVRemote.java

package com.journaldev.design.state;

public class TVRemote {

	public static void main(String[] args) {
		TVContext context = new TVContext();
		State tvStartState = new TVStartState();
		State tvStopState = new TVStopState();
		
		context.setState(tvStartState);
		context.doAction();
		
		
		context.setState(tvStopState);
		context.doAction();
		
	}

}

上記のプログラムの出力は、状態パターンを使用せずにTVリモートの基本実装と同じです。

State Design Pattern Benefits

状態パターンを使用して多様な振る舞いを実装する利点は明らかです。エラーの可能性が少なく、追加の振る舞いの状態を簡単に追加できるため、コードはより堅牢で保守しやすく、柔軟性が向上します。また、このシナリオでのif-elseやswitch-caseの条件ロジックを避けるのに状態パターンが役立ちました。StateパターンはStrategyパターンと非常に似ています。JavaでのStrategyパターンについてもチェックしてみてください。これでJavaのStateデザインパターンに関する説明は終わりです。お楽しみいただければ幸いです。

Source:
https://www.digitalocean.com/community/tutorials/state-design-pattern-java