本文主要是介绍设计模式之十 状态模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
状态模式
目录
目录
状态模式
目录
定义
例子
设计原则
总结
定义
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
例子
我们使用《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;}@Overridepublic void insertQuarter() {System.out.println("你插入了一枚硬币");gumballMachine.setState(gumballMachine.getHasQuarterState());}@Overridepublic void ejectQuarter() {System.out.println("没钱,你不能退钱");}@Overridepublic void turnCrank() {System.out.println("没钱还想要糖果?美得你");}@Overridepublic 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;}@Overridepublic void insertQuarter() {System.out.println("机子里已经插过钱了");}@Overridepublic void ejectQuarter() {System.out.println("退钱成功");gumballMachine.setState(gumballMachine.getNoQuarterState());}@Overridepublic 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());}}@Overridepublic void dispense() {System.out.println("没有糖果发放");}}
/*** 售光状态* @author Kwin**/
public class SoldOutState implements State {private GumballMachine gumballMachine;public SoldOutState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}@Overridepublic void insertQuarter() {System.out.println("别塞,没糖果了");}@Overridepublic void ejectQuarter() {System.out.println("哟呵,想诈骗啊");}@Overridepublic void turnCrank() {System.out.println("说了,没糖果了");}@Overridepublic void dispense() {System.out.println("没糖果了");}}
/*** 销售状态* @author Kwin**/
public class SoldState implements State {private GumballMachine gumballMachine;public SoldState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}@Overridepublic void insertQuarter() {System.out.println("请等待,正在出货中");}@Overridepublic void ejectQuarter() {System.out.println("抱歉,正在出货中");}@Overridepublic void turnCrank() {System.out.println("你想出两次货?美得你");}@Overridepublic 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;}@Overridepublic void insertQuarter() {System.out.println("请等待,正在出货中");}@Overridepublic void ejectQuarter() {System.out.println("抱歉,正在出货中");}@Overridepublic void turnCrank() {System.out.println("你想出两次货?美得你");}@Overridepublic 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()调用的判断条件。
设计原则
封装变化
多用组合,少用继承
针对接口编程,不针对实现编程
为交互对象之间的松耦合设计而努力
类应该对扩展开放,对修改关闭
依赖抽象,不要依赖具体类
只和朋友交谈
别找我,我会找你
类应该只有一个改变的理由
总结
状态模式允许一个对象基于内部状态而拥有不同的行为。
通过将每一个状态封装进一个类,我们以后需要做的任何改变局部化了。
使用状态模式通常会导致设计中的类的数目的大量增加。
这篇关于设计模式之十 状态模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!