5

设计模式与软考试题之状态模式(一)

 3 years ago
source link: https://blog.csdn.net/LoveLion/article/details/8523214
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

设计模式与软考试题之状态模式(一)

      从2006年-2012年,在全国计算机技术与软件专业技术资格(水平)考试软件设计师级别考试中,状态模式已两次作为下午试题的最后一题出现(参考:历年软件设计师下午考试试题汇总统计),分别是2006年下半年和2011年下半年的两次考试。

【全国计算机技术与软件专业技术资格(水平)考试  2006 年下半年 软件设计师 下午试卷】

       注:当年试题六和试题七二选一,试题六为C++版,试题七为Java版。

       试题六

       阅读以下说明和 C++代码,将应填入 (n) 处的字句写在答题纸的对应栏内。

       【说明】

       传输门是传输系统中的重要装置。传输门具有 Open(打开)、Closed(关闭)、Opening(正在打开)、StayOpen(保持打开)、Closing(正在关闭)五种状态。触发传输门状态转 换的事件有 click、complete 和 timeout 三种。事件与其相应的状态转换如图6-1 所示。

 图6-1  传输门响应事件与其状态转换图

       下面的【C++代码 1】与【C++代码 2】分别用两种不同的设计思路对传输门进行状态模拟,请填补代码中的空缺。

【C++代码 1】

const  int  CLOSED  =  1;  const  int  OPENING  =  2;

const  int  OPEN  =  3; const  int  CLOSING  =  4;

const  int  STAYOPEN  =  5;    //定义状态变量,用不同整数表示不同状态

class  Door  {

    private:

    int  state; //传输门当前状态

    void  setState(int  state){ this->state  =  state;  }  //设置当前状态

    public: Door():state(CLOSED){};

    void  getState() {       //根据当前状态输出相应的字符串

        switch(state) {

            case  OPENING:  cout  <<"OPENING" <<  endl; break;

            case  CLOSED:  cout  <<  "CLOSED" <<  endl; break;        

            case  OPEN:  cout  <<  "OPEN" <<  endl;  break;

            case  CLOSING: cout  <<  "CLOSING" <<  endl; break;

            case  STAYOPEN:  cout  <<  "STAYOPEN" <<  endl;  break;

    void  click()  {        //发生click事件时进行状态转换

        if  ((1) )   setState(OPENING);

        else  if  ((2) ) setState(CLOSING);

        else  if  ((3) ) setState(STAYOPEN);

    void  timeout(){        //发生timeout事件时进行状态转换

        if  (state  ==  OPEN)  setState(CLOSING);

    void  complete(){       //发生complete事件时进行状态转换

        if  (state  ==  OPENING)    setState(OPEN);

        else  if  (state  ==  CLOSING)    setState(CLOSED);

int  main() {

    Door  aDoor;

    aDoor.getState();  

    aDoor.click(); 

    aDoor.getState();  

    aDoor.complete();

    aDoor.getState();                   

    aDoor.click(); 

    aDoor.getState();  

    aDoor.click();

    aDoor.getState();  

    return  0;

【C++代码 2】

class  Door  {

    public:

    DoorState  *CLOSED,  *OPENING,  *OPEN,  *CLOSING,  *STAYOPEN,  *state;

    Door();

    virtual  ~Door(){  ……  //释放申请的内存,此处代码省略};

    void  setState(DoorState  *state)  {   this->state  =  state; }

    void  getState(){

        //  此处代码省略,本方法输出状态字符串,

        //  例如,当前状态为CLOSED时,输出字符串为“CLOSED”

    void  click();

    void  timeout();

    void  complete();

Door::Door() {

    CLOSED  =  new DoorClosed(this);

    OPENING  =  new DoorOpening(this);

    OPEN  =  new DoorOpen(this);

    CLOSING  =  new DoorClosing(this);

    STAYOPEN  =  new DoorStayOpen(this); 

    state  =  CLOSED;

void  Door::click() {   (4) ;}

void  Door::timeout() {   (5) ; }

void  Door::complete() {(6) ; }

class  DoorState { //定义一个抽象的状态,它是所有状态类的基类

    protected:  Door  *door;

    public:

    DoorState(Door  *door)  {  this->door  =  door;  }

    virtual  ~DoorState(void);

    virtual  void  click()  {}

    virtual  void  complete()  {}

    virtual  void  timeout()  {}

class  DoorClosed  :public  DoorState{  //定义一个基本的 Closed 状态

    public:

    DoorClosed(Door  *door):DoorState(door)  {}

    virtual  ~ DoorClosed  (){}

    void  click();

void  DoorClosed::click()  {(7) ; }

//  其它状态类的定义与实现代码省略

int  main() {

    Door  aDoor;

    aDoor.getState(); aDoor.click();   aDoor.getState(); aDoor.complete();

    aDoor.getState(); aDoor.timeout(); aDoor.getState(); return  0;

     试题七

       阅读以下说明以及Java程序,将应填入 (n)  处的字句写在答题纸的对应栏内。

       【说明】

传输门是传输系统中的重要装置。传输门具有 Open(打开)、Closed(关闭)、Opening(正在打开)、StayOpen(保持打开)、Closing(正在关闭)五种状态。触发状态的转换事件有 click、complete 和 timeout 三种。事件与其相应的状态转换如图7-1所示。

图7-1  传输门响应事件与其状态转换图

       下面的【Java 代码 1】与【Java 代码 2】分别用两种不同的设计思路对传输门进行状态模拟,请填补代码中的空缺。

【Java代码 1】

public  class  Door  {

    //定义状态变量,用不同的整数表示不同状态

    public static final int CLOSED = 1;

    public static final int OPENING = 2;

    public static final int OPEN  = 3;

    public static final int CLOSING = 4;

    public static final int STAYOPEN = 5;  

    private  int  state  =  CLOSED;

    private void setState(int state){this.state  =  state;} //设置传输门当前状态

    public  void  getState() {

        //  此处代码省略,本方法输出状态字符串,

        //  例如,当前状态为 CLOSED 时,输出字符串为”CLOSED”

    public  void  click()  {   //发生 click 事件时进行状态转换

        if  ((1) )   setState(OPENING);

        else  if  (   (2)     )  setState(CLOSING);

        else  if  ((3) )    setState(STAYOPEN);

    //发生 timeout 事件时进行状态转换

    public  void  timeout() {    if  (state  ==  OPEN)  setState(CLOSING); }

    public  void  complete() { //发生 complete 事件时进行状态转换

        if  (state  ==  OPENING)   setState(OPEN);

        else  if  (state  ==  CLOSING)    setState(CLOSED);

    public  static  void  main(String  []  args){

        Door  aDoor  =  new Door();

       aDoor.getState(); aDoor.click(); aDoor.getState(); aDoor.complete(); aDoor.getState(); aDoor.click();     aDoor.getState(); aDoor.click(); aDoor.getState(); return;

【Java代码 2】

public  class  Door  {

    public  final  DoorState  CLOSED  =  new DoorClosed(this);

    public  final  DoorState  OPENING  =  new DoorOpening(this);

    public  final  DoorState  OPEN  =  new DoorOpen(this);

    public  final  DoorState  CLOSING  =  new DoorClosing(this);

    public final DoorState STAYOPEN  =  new DoorStayOpen(this);

    private  DoorState  state  =  CLOSED;

//设置传输门当前状态

    public void setState(DoorState state){ this.state = state;}

    public  void  getState(){  //根据当前状态输出对应的状态字符串

        System.out.println(state.getClass().getName());

    public  void  click() {   (4) ;}//发生 click 事件时进行状态转换

    public  void  timeout() {     (5) ;}//发生 timeout 事件时进行状态转换

    public  void  complete() {   (6) ;}//发生 complete 事件时进行状态转换

    public  static  void  main(String[]  args){

        Door  aDoor  =  new Door();

        aDoor.getState(); aDoor.click();   aDoor.getState(); aDoor.complete();

        aDoor.getState(); aDoor.timeout(); aDoor.getState(); return;

public  abstract  class  DoorState  {  //定义所有状态类的基类

    protected  Door  door  ;

    public  DoorState(Door  door)  {this.door  =  door;}

    public  void  click()  {} public   void  complete()  {} public  void  timeout()  {}

class  DoorClosed  extends  DoorState{  //定义一个基本的 Closed 状态

    public  DoorClosed(Door  door)  {    super(door);  }

    public  void  click()  {     (7) ;   }

    //该类定义的其余代码省略

//其余代码省略

 ------------------------------------------------------------------------------------------------------------------------------------------------------

    分析与解答:

      本题前三空的难度不大,只要能够看懂状态图并读懂代码,正确填写应该没有太大问题,后四空略有难度,特别是最后一空。在本试题中提供了两种状态转换实现方案:

      【方案一】(即代码一)没有用状态模式,将所有的状态转换代码都写到Door类中,每一个状态对应一个整型常量(状态变量),当Door的click()等方法被调用时,可以实现相应状态的转换,根据状态图,可以完成对(1)、(2)和(3)空的解答,例如当状态变量state为CLOSED或者CLOSING时,调用click()方法,状态将转换为OPENING。同理,当timeout()方法和complete()方法被调用时,某些状态之间也可以发生转换。

      【方案二】(即代码二)使用了状态模式,Door类充当环境类,提供了抽象类DoorState充当抽象状态类,其子类,如DoorClosed、DoorOpening等,充当具体状态类。在环境类Door枚举了所有的状态,提供了一个setState()方法用于设置当前状态,此外,在Door的click()方法中调用状态类的click()方法,在Door的timeout()方法中调用状态类的timeout()方法,在Door的complete()方法中调用状态类的complete()方法。因此,(4)、(5)、(6)空用于实现间接调用。第(7)空用于实现状态的切换,当状态为DoorClosed时,如果调用click()方法,那么Door的当前状态将切换到OPENING,因此在第(7)空,将调用door对象的setState()方法,注入一个DoorOpening类型的对象,由于该对象已存在于Door中,无须再重新创建。在C++中,可以通过door->OPENING来获取,而在Java中则通过door.OPENING来获取。在本试题中,状态的切换由具体状态类来完成,由环境类来维护各个具体状态类的实例。

微笑推荐:深入学习状态模式

      参考答案:

【试题六】

(1) state == CLOSED || state == CLOSING

(2) state == OPENING || state == STAYOPEN

(3) state == OPEN

(4) state -> click()

(5) state -> timeout()

(6) state -> complete()

(7) door -> setState(door->OPENING)

【试题七】

(1) state == CLOSED || state == CLOSING

(2) state == OPENING || state == STAYOPEN

(3) state == OPEN

(4) state.click()

(5) state.timeout()

(6) state.complete()

(7) door.setState(door.OPENING)

【作者:刘伟 http://blog.csdn.net/lovelion


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK