设计模式之状态模式
情景:有一个自动投币的糖果机。它有以下几种状态(每个圆圈代表一个状态): 如果用常量值来定义几个变量 SOLD_OUT = 0 NO_QUARTER = 1 HAS_QUARTER = 2 SOLD = 3<span style="color: #0000ff;">int state = SOLD_OUT;
这样状态变化就可以写成: (state == (state ==
每一个动作都要先判断状态,改后再决定反馈以及下一个状态是什么。 虽然可以实现要求,但是当出现新的状态的时候,很不利于扩展。 我们把状态变成一个类,把不同的状态封装在各自的类中,然后在动作发生时委托给当前状态。 首先,定义状态接口 然后定义各种状态 NoQuarterState
GumballMachine gumballMachine;
</span><span style="color: #0000ff;">public</span><span style="color: #000000;"> NoQuarterState(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 insert a quarter"<span style="color: #000000;">);
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
@Override
</span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> ejectQuarter() {
System.out.println(</span>"You haven't inserted a quarter"<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's no quarter"<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 need to pay first"<span style="color: #000000;">);
}
} <div class="cnblogs_code" onclick="cnblogs_code_show('026e1670-0ced-45f5-9619-b0d2e08d203e')"> HasQuarterState
} <div class="cnblogs_code" onclick="cnblogs_code_show('b32320a8-0f59-4338-9d16-ea46e723673b')"> SoldOutState
} <div class="cnblogs_code" onclick="cnblogs_code_show('fdcdb9e7-168f-4423-92dd-31d604827d7e')"> SoldState
} 最后写一下糖果机 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,Incn" + "Inventory: " +<span style="color: #000000;">
count </span>+ " gumballsn"<span style="color: #000000;">;
}
} 测试类: = GumballMachine(5
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.ejectQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.ejectQuarter();
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
System.out.println(gumballMachine);
}
} 将每一个状态局部化到它自己的类中。将容易产生问题的if语句删除,方便日后的维护。 这样,每一个状态“对修改关闭”,糖果机“对扩展开放” 状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修改了它的类。 类图: 现在我们改变需求,希望有10%的概率中奖,也就是投一个币,获得两个糖果。 我们只需要添加一个新的状态类。 WinnerState
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状态: HasQuarterState
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;"> System.out.println("You turned..."<span style="color: #000000;">); <span style="color: #0000ff;">int winner = randomWinner.nextInt(10<span style="color: #000000;">); <span style="color: #0000ff;">if (winner == 0 && (gumballMachine.getCount() > 1<span style="color: #000000;">)) { gumballMachine.setState(gumballMachine.getWinnerState()); } <span style="color: #0000ff;">else<span style="color: #000000;"> { gumballMachine.setState(gumballMachine.getSoldState()); } }
<span style="color: #000000;"> 记得在糖果机类中添加一个WinnerState状态类,这个新的需求就实现了。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |