情景:有一个自动投币的糖果机。它有以下几种状态(每个圆圈代表一个状态):
如果用常量值来定义几个变量
这样状态变化就可以写成:
每一个动作都要先判断状态,改后再决定反馈以及下一个状态是什么。
虽然可以实现要求,但是当出现新的状态的时候,很不利于扩展。
我们把状态变成一个类,把不同的状态封装在各自的类中,然后在动作发生时委托给当前状态。
首先,定义状态接口
然后定义各种状态
情景:有一个自动投币的糖果机。它有以下几种状态(每个圆圈代表一个状态):
如果用常量值来定义几个变量
这样状态变化就可以写成:
每一个动作都要先判断状态,改后再决定反馈以及下一个状态是什么。
虽然可以实现要求,但是当出现新的状态的时候,很不利于扩展。
我们把状态变成一个类,把不同的状态封装在各自的类中,然后在动作发生时委托给当前状态。
首先,定义状态接口
然后定义各种状态
<div class="cnblogs_code" onclick="cnblogs_code_show('026e1670-0ced-45f5-9619-b0d2e08d203e')">
<img id="code_img_closed_026e1670-0ced-45f5-9619-b0d2e08d203e" class="code_img_closed" src="https://www.jb51.cc/res/2019/02-05/22/1c53668bcee393edac0d7b3b3daff1ae.gif" alt=""><img id="code_img_opened_026e1670-0ced-45f5-9619-b0d2e08d203e" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('026e1670-0ced-45f5-9619-b0d2e08d203e',event)" src="https://www.jb51.cc/res/2019/02-05/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt=""><div id="cnblogs_code_open_026e1670-0ced-45f5-9619-b0d2e08d203e" class="cnblogs_code_hide">
HasQuarterState GumballMachine gumballMachine;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> HasQuarterState(GumballMachine gumballMachine) {
</span><span style="color: #0000ff;">this</span>.gumballMachine =<span style="color: #000000;"> gumballMachine;
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insertQuarter() {
System.out.println(</span>"You can't insert another quater"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> ejectQuarter() {
System.out.println(</span>"Quarter returned"<span style="color: #000000;">);
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> turnCrank() {
System.out.println(</span>"You turned..."<span style="color: #000000;">);
gumballMachine.setState(gumballMachine.getSoldState());
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> dispense() {
System.out.println(</span>"No gumball dispensed"<span style="color: #000000;">);
}
}
<div class="cnblogs_code" onclick="cnblogs_code_show('b32320a8-0f59-4338-9d16-ea46e723673b')">
<img id="code_img_closed_b32320a8-0f59-4338-9d16-ea46e723673b" class="code_img_closed" src="https://www.jb51.cc/res/2019/02-05/22/1c53668bcee393edac0d7b3b3daff1ae.gif" alt=""><img id="code_img_opened_b32320a8-0f59-4338-9d16-ea46e723673b" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('b32320a8-0f59-4338-9d16-ea46e723673b',event)" src="https://www.jb51.cc/res/2019/02-05/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt=""><div id="cnblogs_code_open_b32320a8-0f59-4338-9d16-ea46e723673b" class="cnblogs_code_hide">
SoldOutState GumballMachine gumballMachine;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> SoldOutState(GumballMachine gumballMachine) {
</span><span style="color: #0000ff;">this</span>.gumballMachine =<span style="color: #000000;"> gumballMachine;
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insertQuarter() {
System.out.println(</span>"You can't insert a quarter,the machine is sold out"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> ejectQuarter() {
System.out.println(</span>"You can't eject,you haven't inserted a quarter yet"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> turnCrank() {
System.out.println(</span>"You turned,but there are no gumballs"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> dispense() {
System.out.println(</span>"No gumball dispensed"<span style="color: #000000;">);
}
}
<div class="cnblogs_code" onclick="cnblogs_code_show('fdcdb9e7-168f-4423-92dd-31d604827d7e')">
<img id="code_img_closed_fdcdb9e7-168f-4423-92dd-31d604827d7e" class="code_img_closed" src="https://www.jb51.cc/res/2019/02-05/22/1c53668bcee393edac0d7b3b3daff1ae.gif" alt=""><img id="code_img_opened_fdcdb9e7-168f-4423-92dd-31d604827d7e" class="code_img_opened" style="display: none;" onclick="cnblogs_code_hide('fdcdb9e7-168f-4423-92dd-31d604827d7e',event)" src="https://www.jb51.cc/res/2019/02-05/22/405b18b4b6584ae338e0f6ecaf736533.gif" alt=""><div id="cnblogs_code_open_fdcdb9e7-168f-4423-92dd-31d604827d7e" class="cnblogs_code_hide">
SoldState GumballMachine gumballMachine;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> SoldState(GumballMachine gumballMachine) {
</span><span style="color: #0000ff;">this</span>.gumballMachine =<span style="color: #000000;"> gumballMachine;
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insertQuarter() {
System.out.println(</span>"Please wait,we're already giving you a gumball"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> ejectQuarter() {
System.out.println(</span>"Sorry,you already turned the crank"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> turnCrank() {
System.out.println(</span>"Turning twice doesn't get you another gumball!"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> dispense() {
gumballMachine.releaseBall();
</span><span style="color: #0000ff;">if</span> (gumballMachine.getCount() > 0<span style="color: #000000;">) {
gumballMachine.setState(gumballMachine.getNoQuarterState());
} </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
System.out.println(</span>"Oops,out of gumballs!"<span style="color: #000000;">);
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}
最后写一下糖果机
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State state </span>=<span style="color: #000000;"> soldOutState;
</span><span style="color: #0000ff;">int</span> count = 0<span style="color: #000000;">;
</span><span style="color: #0000ff;">public</span> GumballMachine(<span style="color: #0000ff;">int</span><span style="color: #000000;"> numberGumballs) {
soldOutState </span>= <span style="color: #0000ff;">new</span> SoldOutState(<span style="color: #0000ff;">this</span><span style="color: #000000;">);
noQuarterState </span>= <span style="color: #0000ff;">new</span> NoQuarterState(<span style="color: #0000ff;">this</span><span style="color: #000000;">);
hasQuarterState </span>= <span style="color: #0000ff;">new</span> HasQuarterState(<span style="color: #0000ff;">this</span><span style="color: #000000;">);
soldState </span>= <span style="color: #0000ff;">new</span> SoldState(<span style="color: #0000ff;">this</span><span style="color: #000000;">);
count </span>=<span style="color: #000000;"> numberGumballs;
</span><span style="color: #0000ff;">if</span> (numberGumballs > 0<span style="color: #000000;">) {
state </span>=<span style="color: #000000;"> noQuarterState;
}
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insertQuarter() {
state.insertQuarter();
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> ejectQuarter() {
state.ejectQuarter();
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> turnCrank() {
state.turnCrank();
state.dispense();
}
</span><span style="color: #0000ff;">void</span><span style="color: #000000;"> setState(State state) {
</span><span style="color: #0000ff;">this</span>.state =<span style="color: #000000;"> state;
}
</span><span style="color: #0000ff;">void</span><span style="color: #000000;"> releaseBall() {
System.out.println(</span>"A gumball comes rolling out the slot..."<span style="color: #000000;">);
</span><span style="color: #0000ff;">if</span> (count != 0<span style="color: #000000;">) {
count </span>-= 1<span style="color: #000000;">;
}
}
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getCount() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> count;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> State getSoldOutState() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> soldOutState;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> State getNoQuarterState() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> noQuarterState;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> State getHasQuarterState() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> hasQuarterState;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> State getSoldState() {
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> soldState;
}
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> String toString() {
</span><span style="color: #0000ff;">return</span> "\nMighty Gumball,Inc\n" + "Inventory: " +<span style="color: #000000;">
count </span>+ " gumballs\n"<span style="color: #000000;">;
}
}
测试类:
将每一个状态局部化到它自己的类中。将容易产生问题的if语句删除,方便日后的维护。
这样,每一个状态“对修改关闭”,糖果机“对扩展开放”
状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修改了它的类。
类图:
现在我们改变需求,希望有10%的概率中奖,也就是投一个币,获得两个糖果。
我们只需要添加一个新的状态类。
GumballMachine gumballMachine;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> WinnerState(GumballMachine gumballMachine) {
</span><span style="color: #0000ff;">this</span>.gumballMachine =<span style="color: #000000;"> gumballMachine;
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insertQuarter() {
System.out.println(</span>"Please wait,you already turned the crank"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> turnCrank() {
System.out.println(</span>"Turning twice doesn't get you another gumball!"<span style="color: #000000;">);
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> dispense() {
System.out.println(</span>"YOU'RE A WINNER! YOU GET TWO GUMBALLS FOR YOUR QUARTERS"<span style="color: #000000;">);
gumballMachine.releaseBall();
</span><span style="color: #0000ff;">if</span> (gumballMachine.getCount() == 0<span style="color: #000000;">) {
gumballMachine.setState(gumballMachine.getSoldOutState());
} </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
gumballMachine.releaseBall();
</span><span style="color: #0000ff;">if</span> (gumballMachine.getCount() > 0<span style="color: #000000;">) {
gumballMachine.setState(gumballMachine.getNoQuarterState());
} </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {
System.out.println(</span>"Oops,out of gumballs!"<span style="color: #000000;">);
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}
}
在HasQuarterState中有几率跳到WinnerState状态:
GumballMachine gumballMachine;
Random randomWinner </span>= <span style="color: #0000ff;">new</span><span style="color: #000000;"> Random(System.currentTimeMillis());
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ....</span>
<span style="color: #000000;">
@Override
</span><span style="color: #008000;">//</span><span style="color: #008000;"> ....</span>
<span style="color: #000000;">
}
记得在糖果机类中添加一个WinnerState状态类,这个新的需求就实现了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。