设计模式之状态模式

前端之家收集整理的这篇文章主要介绍了设计模式之状态模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

情景:有一个自动投币的糖果机。它有以下几种状态(每个圆圈代表一个状态):

如果用常量值来定义几个变量

SOLD_OUT = 0 NO_QUARTER = 1 HAS_QUARTER = 2 SOLD = 3<span style="color: #0000ff;">int state = SOLD_OUT;

这样状态变化就可以写成:

(state == (state ==

每一个动作都要先判断状态,改后再决定反馈以及下一个状态是什么。

虽然可以实现要求,但是当出现新的状态的时候,很不利于扩展。

我们把状态变成一个类,把不同的状态封装在各自的类中,然后在动作发生时委托给当前状态。

首先,定义状态接口

然后定义各种状态

<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="/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="/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;"&gt;public</span><span style="color: #000000;"&gt; HasQuarterState(GumballMachine gumballMachine) {
    </span><span style="color: #0000ff;"&gt;this</span>.gumballMachine =<span style="color: #000000;"&gt; gumballMachine;
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; insertQuarter() {
    System.out.println(</span>"You can't insert another quater"<span style="color: #000000;"&gt;);        
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; ejectQuarter() {
    System.out.println(</span>"Quarter returned"<span style="color: #000000;"&gt;);
    gumballMachine.setState(gumballMachine.getNoQuarterState());
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; turnCrank() {
    System.out.println(</span>"You turned..."<span style="color: #000000;"&gt;);
    gumballMachine.setState(gumballMachine.getSoldState());
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; dispense() {
    System.out.println(</span>"No gumball dispensed"<span style="color: #000000;"&gt;);
}

}

<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="/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="/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;"&gt;public</span><span style="color: #000000;"&gt; SoldOutState(GumballMachine gumballMachine) {
    </span><span style="color: #0000ff;"&gt;this</span>.gumballMachine =<span style="color: #000000;"&gt; gumballMachine;
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; insertQuarter() {
    System.out.println(</span>"You can't insert a quarter,the machine is sold out"<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; ejectQuarter() {
    System.out.println(</span>"You can't eject,you haven't inserted a quarter yet"<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; turnCrank() {
    System.out.println(</span>"You turned,but there are no gumballs"<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; dispense() {
    System.out.println(</span>"No gumball dispensed"<span style="color: #000000;"&gt;);
}

}

<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="/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="/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;"&gt;public</span><span style="color: #000000;"&gt; SoldState(GumballMachine gumballMachine) {
    </span><span style="color: #0000ff;"&gt;this</span>.gumballMachine =<span style="color: #000000;"&gt; gumballMachine;
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; insertQuarter() {
    System.out.println(</span>"Please wait,we're already giving you a gumball"<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; ejectQuarter() {
    System.out.println(</span>"Sorry,you already turned the crank"<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; turnCrank() {
    System.out.println(</span>"Turning twice doesn't get you another gumball!"<span style="color: #000000;"&gt;);
}

@Override
</span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; dispense() {
    gumballMachine.releaseBall();
    </span><span style="color: #0000ff;"&gt;if</span> (gumballMachine.getCount() > 0<span style="color: #000000;"&gt;) {
        gumballMachine.setState(gumballMachine.getNoQuarterState());
    } </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt; {
        System.out.println(</span>"Oops,out of gumballs!"<span style="color: #000000;"&gt;);
        gumballMachine.setState(gumballMachine.getSoldOutState());
    }
}

}

最后写一下糖果机

State soldOutState; State noQuarterState; State hasQuarterState; State soldState; State state </span>=<span style="color: #000000;"&gt; soldOutState; </span><span style="color: #0000ff;"&gt;int</span> count = 0<span style="color: #000000;"&gt;; </span><span style="color: #0000ff;"&gt;public</span> GumballMachine(<span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; numberGumballs) { soldOutState </span>= <span style="color: #0000ff;"&gt;new</span> SoldOutState(<span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;); noQuarterState </span>= <span style="color: #0000ff;"&gt;new</span> NoQuarterState(<span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;); hasQuarterState </span>= <span style="color: #0000ff;"&gt;new</span> HasQuarterState(<span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;); soldState </span>= <span style="color: #0000ff;"&gt;new</span> SoldState(<span style="color: #0000ff;"&gt;this</span><span style="color: #000000;"&gt;); count </span>=<span style="color: #000000;"&gt; numberGumballs; </span><span style="color: #0000ff;"&gt;if</span> (numberGumballs > 0<span style="color: #000000;"&gt;) { state </span>=<span style="color: #000000;"&gt; noQuarterState; } } </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; insertQuarter() { state.insertQuarter(); } </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; ejectQuarter() { state.ejectQuarter(); } </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; turnCrank() { state.turnCrank(); state.dispense(); } </span><span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; setState(State state) { </span><span style="color: #0000ff;"&gt;this</span>.state =<span style="color: #000000;"&gt; state; } </span><span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; releaseBall() { System.out.println(</span>"A gumball comes rolling out the slot..."<span style="color: #000000;"&gt;); </span><span style="color: #0000ff;"&gt;if</span> (count != 0<span style="color: #000000;"&gt;) { count </span>-= 1<span style="color: #000000;"&gt;; } } </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;int</span><span style="color: #000000;"&gt; getCount() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; count; } </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; State getSoldOutState() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; soldOutState; } </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; State getNoQuarterState() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; noQuarterState; } </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; State getHasQuarterState() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; hasQuarterState; } </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; State getSoldState() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; soldState; } </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; String toString() { </span><span style="color: #0000ff;"&gt;return</span> "\nMighty Gumball,Inc\n" + "Inventory: " +<span style="color: #000000;"&gt; count </span>+ " gumballs\n"<span style="color: #000000;"&gt;; }

}

测试类:

将每一个状态局部化到它自己的类中。将容易产生问题的if语句删除,方便日后的维护。

这样,每一个状态“对修改关闭”,糖果机“对扩展开放”

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

类图:

现在我们改变需求,希望有10%的概率中奖,也就是投一个币,获得两个糖果。

我们只需要添加一个新的状态类。

WinnerState GumballMachine gumballMachine; </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; WinnerState(GumballMachine gumballMachine) { </span><span style="color: #0000ff;"&gt;this</span>.gumballMachine =<span style="color: #000000;"&gt; gumballMachine; } @Override </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; insertQuarter() { System.out.println(</span>"Please wait,you already turned the crank"<span style="color: #000000;"&gt;); } @Override </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; turnCrank() { System.out.println(</span>"Turning twice doesn't get you another gumball!"<span style="color: #000000;"&gt;); } @Override </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; dispense() { System.out.println(</span>"YOU'RE A WINNER! YOU GET TWO GUMBALLS FOR YOUR QUARTERS"<span style="color: #000000;"&gt;); gumballMachine.releaseBall(); </span><span style="color: #0000ff;"&gt;if</span> (gumballMachine.getCount() == 0<span style="color: #000000;"&gt;) { gumballMachine.setState(gumballMachine.getSoldOutState()); } </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt; { gumballMachine.releaseBall(); </span><span style="color: #0000ff;"&gt;if</span> (gumballMachine.getCount() > 0<span style="color: #000000;"&gt;) { gumballMachine.setState(gumballMachine.getNoQuarterState()); } </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt; { System.out.println(</span>"Oops,out of gumballs!"<span style="color: #000000;"&gt;); gumballMachine.setState(gumballMachine.getSoldOutState()); } } }

}

在HasQuarterState中有几率跳到WinnerState状态:

HasQuarterState GumballMachine gumballMachine; Random randomWinner </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; Random(System.currentTimeMillis()); </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; ....</span>

<span style="color: #000000;">
@Override
<span style="color: #0000ff;">public <span style="color: #0000ff;">void<span style="color: #000000;"> turnCrank() {
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><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; ....</span>

<span style="color: #000000;">
}

记得在糖果机类中添加一个WinnerState状态类,这个新的需求就实现了。

猜你在找的设计模式相关文章