Singleton 和 Monostate 模式

Singleton 和 Monostate 模式

怎样才能使得两个实例表现得像一个对象呢?很简单,只要把所有的变量都变成静态变量即可。

public class Monostate {

	private static int itsX = 0;
	
	public Monostate() {
		
	}
	
	public void setX(final int x) {
		itsX = x;
	}
	
	public int getX() {
		return itsX;
	}
}

实现地铁十字转门的简单的有限状态机。十字转门开始时处于Locked 状态。如果投入一枚硬币,它就迁移到Unlocked 状态,开启转门,复位可能出现的任何告警状态,并把硬币放到收集箱柜中。如果此时乘客通过了转门,转门就迁移回Locked 状态并把门锁上。

 

实现类

public class Turnstile {

	/**
	 * 是否已锁.
	 */
	private static boolean isLocked = true;
	/**
	 * 是否报警中.
	 */
	private static boolean isAlarming = false;
	/**
	 * 硬币数.
	 */
	private static int itsCoins = 0;
	/**
	 * 退款数.
	 */
	private static int itsRefunds = 0;
	protected static final Turnstile LOCKED = new Locked();
	protected static final Turnstile UNLOCKED = new Unlocked();
	protected static Turnstile itsState = LOCKED;
	
	public void reset() {
		lock(true);
		alarm(false);
		itsCoins = 0;
		itsRefunds = 0;
		itsState = LOCKED;
	}
	
	public boolean locked() {
		return isLocked;
	}
	
	public boolean alarm() {
		return isAlarming;
	}
	
	/**
	 * 投币.
	 */
	public void coin() {
		itsState.coin();
	}
	
	/**
	 * 通过.
	 */
	public void pass() {
		itsState.pass();
	}
	
	/**
	 * 设置锁住.
	 * @param shouldLock
	 */
	protected void lock(boolean shouldLock) {
		isLocked = shouldLock;
	}
	
	/**
	 * 设置报警.
	 * @param shouldAlarm
	 */
	protected void alarm(boolean shouldAlarm) {
		isAlarming = shouldAlarm;
	}
	
	/**
	 * 获取投币数.
	 * @return
	 */
	public int coins() {
		return itsCoins;
	}
	
	/**
	 * 获取退款数.
	 * @return
	 */
	public int refunds() {
		return itsRefunds;
	}
	
	/**
	 * 存钱.
	 */
	public void deposit() {
		itsCoins++;
	}
	
	/**
	 * 退款.
	 */
	public void refund() {
		itsRefunds++;
	}
	
	static class Locked extends Turnstile {
		public void coin() {
			Turnstile.itsState = UNLOCKED;
			lock(false);
			alarm(false);
			deposit();
		}
		
		public void pass() {
			alarm(true);
		}
	}
	
	static class Unlocked extends Turnstile {
		public void coin() {
			refund();
		}
		
		public void pass() {
			lock(true);
			itsState = LOCKED;
		}
	}
}

测试类

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;


public class TurnstileTest {
	
	@Before
	public void before() {
		// 每次@Test前执行.
		Turnstile t = new Turnstile();
		t.reset();
	}

	@Test
	public void whenInit() {
		Turnstile t = new Turnstile();
		Assert.assertTrue(t.locked());
	}
	
	@Test
	public void whenCoin() {
		Turnstile t = new Turnstile();
		t.coin();
		Turnstile t1 = new Turnstile();
		Assert.assertTrue(!t1.locked());
		Assert.assertEquals(1, t1.coins());
	}
	
	@Test
	public void whenCoinAndPass() {
		Turnstile t = new Turnstile();
		t.coin();
		t.pass();
		
		Turnstile t1 = new Turnstile();
		Assert.assertTrue(t1.locked());
		Assert.assertTrue(!t1.alarm());
		Assert.assertEquals(1, t1.coins());
	}
	
	@Test
	public void whenTowCoins() {
		Turnstile t = new Turnstile();
		t.coin();
		t.coin();
		
		Turnstile t1 = new Turnstile();
		Assert.assertTrue(!t1.locked());
		Assert.assertEquals(1, t1.coins());
		Assert.assertEquals(1, t1.refunds());
		Assert.assertTrue(!t1.alarm());
	}
	
	@Test
	public void whenPass() {
		Turnstile t = new Turnstile();
		t.pass();
		
		Turnstile t1 = new Turnstile();
		Assert.assertTrue(t1.alarm());
		Assert.assertTrue(t1.locked());
	}
	
	@Test
	public void whenCancelAlarm() {
		Turnstile t = new Turnstile();
		t.pass();
		t.coin();
		
		Turnstile t1 = new Turnstile();
		Assert.assertTrue(!t1.alarm());
		Assert.assertTrue(!t1.locked());
		Assert.assertEquals(1, t1.coins());
		Assert.assertEquals(0, t1.refunds());
	}
	
	@Test
	public void whenTwoOperations() {
		Turnstile t = new Turnstile();
		t.coin();
		t.pass();
		t.coin();
		
		Assert.assertTrue(!t.locked());
		Assert.assertEquals(2, t.coins());
		t.pass();
		Assert.assertTrue(t.locked());
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值