Stateパターンの実装。InBoxState or OutBoxState 自分の小さな「箱」から脱出する方法

移転しました。






アービンジャー インスティチュート,金森 重樹,冨永 星
大和書房 2006-10-19
¥ 1,680


久々に、自分の小さな「箱」から脱出する方法を読み返しました。相変わらず、自分を裏切り続ける毎日だなと自己嫌悪に陥りながらも、ちょっとずつ自分を裏切らず、衝動にしたがって動いてもいいかなと。


同時に、プログラムにおいて、状態をうまく表したいときにどうすればいいんだろう?という疑問からStateパターンに行き着いたので、箱に入った状態と箱から出ている状態をStateパターンで表現してみました。

Stateパターン 状態をクラスとして表現する

「状態」をクラスとして表現していれば、
  • クラスを切り替えることによって「状態野変化」があらわせる。
  • 新しい状態を追加する際、何をプログラムすればよいかはっきりする。

自分の小さな「箱」から脱出する方法

Stateを実装し、InBoxStateとOutBoxStateを作成。
うーん、こんなんでいいのかな。

自分を裏切ったとき、人は箱に入る
I i = new I();
if( i.betray(myself)){
   i.changeState();
}
i.getStatus() => "InBox"
箱に入った状態で誰かとしゃべっても自分のことしか考えない。相手を物としか考えない

自分が持つ正当化イメージを守ろうとする。世界は自分を中心に回っていると考えてしまう。

i.talk(); => "think about myself"
箱に入っていることに気付き、相手を一人の人間として接するとき知らぬ間に箱から出ている
if(i.realize()){
   i.changeState();
}
i.getStatus() => "OutBox"
i.talk(); => "think about you"
箱から出て、テストが通ればOK(笑)

コードも心理状態も箱の外のグリーンな気持ちでいつもいれたらいいですね。


package state.box;

public interface State {
	public abstract String talk();
	public abstract String feel();
	public abstract String getStatus();
	public abstract State changeState();
}
package state.box;

public class OutBoxState implements State {
	
	private static OutBoxState singleton = new OutBoxState();

	public static State getInstance() {
		return singleton;
	}

	@Override
	public String talk() {
		return "think about you";
	}

	@Override
	public String feel() {
		return "calm";
	}
	
	@Override
	public String getStatus() {
		return "OutBox";
	}

	@Override
	public State changeState() {
		return InBoxState.getInstance();
	}

}
package state.box;

public class I {

	private State state = OutBoxState.getInstance();
	
	public String talk() {
		return state.talk();
	}

	public String getStatus() {
		return state.getStatus();
	}

	public void changeState() {
		this.state = state.changeState();
	}
	
	public String feel(){
		return state.feel();
	}
	
}
package state.box;

public class InBoxState implements State {
	
	private static InBoxState singleton = new InBoxState();

	public static State getInstance() {
		return singleton;
	}

	@Override
	public String talk() {
		return "think about myself";
	}
	
	@Override
	public String feel() {
		return "angry";
	}

	@Override
	public String getStatus() {
		return "InBox";
	}

	@Override
	public State changeState() {
		return OutBoxState.getInstance();
	}
}
package test.state.box;

import junit.framework.Assert;

import org.junit.Test;

import state.box.I;

public class BoxTest {
	
	
	@Test
	public void 初期状態は箱の外(){
		I i = new I();
		Assert.assertEquals("OutBox", i.getStatus());
	}
	
	@Test
	public void 自分を裏切ると箱の中に入る(){
		I i = new I();
		i.changeState();
		Assert.assertEquals("InBox", i.getStatus());
	}
	
	@Test
	public void 自分が箱に入ってると気づいたとき箱の外に出る(){
		I i = new I();
		i.changeState();
		i.changeState();
		Assert.assertEquals("OutBox", i.getStatus());
	}
	
	@Test
	public void 箱の外で誰かと話すと相手を一人の人間としてみる(){
		I i = new I();
		Assert.assertEquals("think about you", i.talk());
	}
	
	@Test
	public void 箱に入った状態で誰かと話すと自分のことしか考えない(){
		I i = new I();
		i.changeState();
		Assert.assertEquals("think about myself", i.talk());
	}
	
	@Test
	public void 箱の外の気分(){
		I i = new I();
		Assert.assertEquals("calm", i.feel());
	}
	
	@Test
	public void 箱の中の気分(){
		I i = new I();
		i.changeState();
		Assert.assertEquals("angry", i.feel());
	}
	
}