设计模式之十 状态模式

状态模式

目录

目录

状态模式

目录

定义

例子

设计原则

总结


定义

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

 

例子

我们使用《Head First 设计模式》中的糖果机例子:

糖果机有NoQuarter、HasQuarter、Sold、SoldOut等状态,当然,我们后期可以根据需求加入Winner状态。

首先,让我们创建一个接口,让所有的状态都必须实现这个接口:

/**
 * 状态类
 * @author Kwin
 *
 */
public interface State {

	void insertQuarter();
	void ejectQuarter();
	void turnCrank();
	void dispense();
}

我们实现下面四个状态,后面添加一个赢家状态:

/**
 * 未投硬币状态
 * @author Kwin
 *
 */
public class NoQuarterState implements State {
	private GumballMachine gumballMachine;
	
	public NoQuarterState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
	@Override
	public void insertQuarter() {
		System.out.println("你插入了一枚硬币");
		gumballMachine.setState(gumballMachine.getHasQuarterState());

	}

	@Override
	public void ejectQuarter() {
		System.out.println("没钱,你不能退钱");
	}

	@Override
	public void turnCrank() {
		System.out.println("没钱还想要糖果?美得你");
	}

	@Override
	public void dispense() {
		System.out.println("你要先付钱");
	}

}
/**
 * 已投硬币状态
 * @author Kwin
 *
 */
public class HasQuarterState implements State {
	
	Random randomWinner = new Random(System.currentTimeMillis());

	private GumballMachine gumballMachine;
	
	public HasQuarterState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
	@Override
	public void insertQuarter() {
		System.out.println("机子里已经插过钱了");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("退钱成功");
		gumballMachine.setState(gumballMachine.getNoQuarterState());
	}

	@Override
	public void turnCrank() {
		System.out.println("等待出货");
		int winner = randomWinner.nextInt(10);
		if(winner == 0 && gumballMachine.getCount() > 1) {
			gumballMachine.setState(gumballMachine.getWinnerState());
		}else {
			gumballMachine.setState(gumballMachine.getSoldState());
		}
	}

	@Override
	public void dispense() {
		System.out.println("没有糖果发放");
	}

}
/**
 * 售光状态
 * @author Kwin
 *
 */
public class SoldOutState implements State {

	private GumballMachine gumballMachine;
	
	public SoldOutState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
	@Override
	public void insertQuarter() {
		System.out.println("别塞,没糖果了");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("哟呵,想诈骗啊");
	}

	@Override
	public void turnCrank() {
		System.out.println("说了,没糖果了");
	}

	@Override
	public void dispense() {
		System.out.println("没糖果了");
	}

}
/**
 * 销售状态
 * @author Kwin
 *
 */
public class SoldState implements State {
	private GumballMachine gumballMachine;
	
	public SoldState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
	@Override
	public void insertQuarter() {
		System.out.println("请等待,正在出货中");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("抱歉,正在出货中");
	}

	@Override
	public void turnCrank() {
		System.out.println("你想出两次货?美得你");
	}

	@Override
	public void dispense() {
		gumballMachine.releaseBall();
		if(gumballMachine.getCount() >0) {
			gumballMachine.setState(gumballMachine.getNoQuarterState());
		} else {
			System.out.println("卖完啦!");
			gumballMachine.setState(gumballMachine.getSoldOutState());
		}
	}
}
/**
 * 赢家状态
 * @author Kwin
 *
 */
public class WinnerState implements State {
	private GumballMachine gumballMachine;
	
	public WinnerState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
	@Override
	public void insertQuarter() {
		System.out.println("请等待,正在出货中");
	}

	@Override
	public void ejectQuarter() {
		System.out.println("抱歉,正在出货中");
	}

	@Override
	public void turnCrank() {
		System.out.println("你想出两次货?美得你");
	}

	@Override
	public void dispense() {
		gumballMachine.releaseBall();
		if(gumballMachine.getCount() > 0) {
			gumballMachine.releaseBall();
			if(gumballMachine.getCount() > 0) {
				gumballMachine.setState(gumballMachine.getNoQuarterState());
			} else {
				gumballMachine.setState(gumballMachine.getSoldOutState());
			}
		} else {
			System.out.println("卖完啦!");
			gumballMachine.setState(gumballMachine.getSoldOutState());
		}
	}
}

让我们测试下我们的代码吧

/**
 * 测试代码
 * @author Kwin
 *
 */
public class GumballMachineTestDriver {

	public static void main(String[] args) {
		GumballMachine gumballMachine = new GumballMachine(10);
		System.out.println(gumballMachine);
		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
		
		System.out.println(gumballMachine);
		gumballMachine.insertQuarter();
		gumballMachine.ejectQuarter();
		gumballMachine.ejectQuarter();
		
		System.out.println(gumballMachine);
		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
	}
}

测试结果:

上面的代码还有很多改进的地方,比如:可以把State接口改写成抽象类,把每个方法的默认行为放在其中,并把Context上下文的注入放进其中。

despense()方法一直被调用,我们可以让turnCrank()返回一个布尔值作为对despense()调用的判断条件。

 

 

 

 

 

 

设计原则

封装变化

多用组合,少用继承

针对接口编程,不针对实现编程

为交互对象之间的松耦合设计而努力

类应该对扩展开放,对修改关闭

依赖抽象,不要依赖具体类

只和朋友交谈

别找我,我会找你

类应该只有一个改变的理由

 

总结

状态模式允许一个对象基于内部状态而拥有不同的行为。

通过将每一个状态封装进一个类,我们以后需要做的任何改变局部化了。

使用状态模式通常会导致设计中的类的数目的大量增加。

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值