2011年下半年软件设计师考试下午试题最后一题考查状态模式,在本试题中,命题人设计了一个具有多个状态的纸巾售卖机,真题如下:
【全国计算机技术与软件专业技术资格(水平)考试 2011 年下半年 软件设计师 下午试卷】
注:当年试题五和试题六二选一,试题五为C++版,试题六为Java版。
试题五
阅读以下说明和 C++代码,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
某大型商场内安装了多个简易的纸巾售卖机,自动出售2元钱一包的纸巾,且每次仅售出一包纸巾。纸巾售卖机的状态图如图5-1所示。
图5-1 纸巾售卖机状态图
采用状态(State)模式来实现该纸巾售卖机,得到如图5-2所示的类图。其中类State为抽象类,定义了投币、退币、出纸巾等方法接口。类SoldState、SoldOutState、NoQuarterState和HasQuarterState分别对应图5-1中纸巾售卖机的4种状态:售出纸巾、纸巾售完、没有投币、有2元钱。
图5-2 类图
【C++代码】
#include <iostream>
using namespace std;
// 以下为类的定义部分
class TissueMachine; // 类的提前引用
class State {
public:
virtual void insertQuarter() = 0; //投币
virtual void ejectQuarter() = 0; //退币
virtual void turnCrank()= 0; //按下“出纸巾”按钮
virtual void dispense() = 0; //出纸巾
};
/* 类SoldOutState、NoQuarterState、HasQuarterState、SoldState的定义省略,每个类中均定义了私有数据成员TissueMachine* tissueMachine; */
class TissueMachine {
private:
(1) *soldOutState, *noQuarterState,*hasQuarterState,*soldState, *state ;
int count; //纸巾数
public:
TissueMachine(int numbers);
void setState(State* state);
State* getHasQuarterState();
State* getNoQuarterState();
State* getSoldState();
State* getSoldOutState();
int getCount();
// 其余代码省略
};
// 以下为类的实现部分
void NoQuarterState ::insertQuarter() {
tissueMachine->setState( (2) );
}
void HasQuarterState ::ejectQuarter() {
tissueMachine->setState( (3) );
}
void SoldState ::dispense() {
if(tissueMachine->getCount() > 0) {
tissueMachine->setState( (4) );
}
else {
tissueMachine->setState( (5) );
}
} //其余代码省略
试题六
阅读以下说明以及Java程序,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
某大型商场内安装了多个简易的纸巾售卖机,自动出售2元钱一包的纸巾,且每次仅售出一包纸巾。纸巾售卖机的状态图如图6-1所示。
图6-1 纸巾售卖机状态图
采用状态(State)模式来实现该纸巾售卖机,得到如图6-2所示的类图。其中类State为抽象类,定义了投币、退币、出纸巾等方法接口。类SoldState、SoldOutState、NoQuarterState和HasQuarterState分别对应图6-1中纸巾售卖机的4种状态:售出纸巾、纸巾售完、没有投币、有2元钱。
图6-2 类图
【Java代码】
import java.util.*;
interface State {
public void insertQuarter(); //投币
public void ejectQuarter(); //退币
public void turnCrank(); //按下“出纸巾”按钮
public void dispense(); //出纸巾
}
class TissueMachine {
(1) soldOutState, noQuarterState,hasQuarterState, soldState, state;
state = soldOutState;
intcount = 0; //纸巾数
public TissueMachine(int numbers) { /* 实现代码省略 */ }
public State getHasQuarterState() { returnhasQuarterState; }
public State getNoQuarterState() { return noQuarterState; }
public State getSoldState() { return soldState; }
public State getSoldOutState() { return soldOutState; }
public int getCount() { return count; }
// 其余代码省略
}
class NoQuarterState implements State {
TissueMachine tissueMachine;
public void insertQuarter() {
tissueMachine.setState( (2) );
}
//构造方法以及其余代码省略
}
class HasQuarterState implements State {
TissueMachine tissueMachine;
public void ejectQuarter() {
tissueMachine.setState( (3) );
}
//构造方法以及其余代码省略
}
class SoldState implements State {
TissueMachine tissueMachine;
public void dispense() {
if (tissueMachine.getCount() > 0) {
tissueMachine.setState( (4) );
}
else {
tissueMachine.setState( (5) ); }
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------
分析与解答:
与2006年下半年的那道题相比(参考:设计模式与软考试题之状态模式(一)),本题的难度更小,只提供了使用状态模式的解决方案,没有Non-Pattern解决方案。在环境类TissueMachine中,枚举了各种具体状态并定义了当前状态对象state,在声明状态对象时需使用抽象状态类State,因此空(1)为State。空(2)-空(5)没有啥技术含量,看图说话而已,,这几空都围绕对象状态之间的转换,只要看得懂图1并且知道各种对象状态与状态类之间的对应关系,回答起来就很容易了,例如第(2)空,具体状态类NoQuarterState对应“没有投币”状态,此时,当调用insertQuarter()方法时,纸巾售卖机的状态将切换到“有2元钱”,因此setState()方法中的参数应该为具体状态类HasQuarterState对象,该对象已存在于环境类TissueMachine中,可以通过tissueMachine->getHasQuarterState()或tissueMachine.getHasQuarterState()来获取,第(3)-(5)空与之类似。
在本试题中,状态的切换由具体状态类来完成,环境类负责维护各个具体状态类的实例。
推荐:深入学习状态模式
参考答案:
【试题五】
(1) State
(2) tissueMachine->getHasQuarterState()
(3) tissueMachine->getNoQuarterState()
(4) tissueMachine->getNoQuarterState()
(5) tissueMachine->getSoldOutState()
【试题六】
(1) State
(2) tissueMachine.getHasQuarterState()
(3) tissueMachine.getNoQuarterState()
(4) tissueMachine.getNoQuarterState()
(5) tissueMachine.getSoldOutState()
【作者:刘伟 http://blog.csdn.net/lovelion】