C++ Programmer's Cookbook

{C++ 基础} {C++ 高级} {C#界面,C++核心算法} {设计模式} {C#基础}

模式设计c#--行为型--state

名称 State
结构 o_state.bmp
意图 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
适用性
  • 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
  • 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。S t a t e模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

namespace  State_DesignPattern
{
    
using  System;

    
abstract   class  State 
    
{
        
protected   string  strStatename;        

        
abstract   public   void  Pour();
        
//  do something state-specific here
    }


    
class  OpenedState : State 
    
{        
        
public  OpenedState ()
        
{
            strStatename 
=   " Opened " ;
        }

        
override   public   void  Pour()
        
{
            Console.WriteLine(
" pouring " );
            Console.WriteLine(
" pouring " );
            Console.WriteLine(
" pouring " );
        }

    }

    
    
class  ClosedState : State 
    
{        
        
public  ClosedState()
        
{
            strStatename 
=   " Closed " ;
        }

        
override   public   void  Pour()
        
{
            Console.WriteLine(
" ERROR - bottle is closed - cannot pour " );
        }

    }


    
class  ContextColaBottle 
    
{
        
public   enum  BottleStateSetting  {
            Closed,
            Opened
        }
;

        
//  If teh state classes had large amounts of instance data,
        
//  we could dynamically create them as needed - if this demo
        
//  they are tiny, so we just  create them as data members
        OpenedState openedState  =   new  OpenedState();
        ClosedState closedState 
=   new  ClosedState();

        
public  ContextColaBottle ()
        
{
            
//  Initialize to closed
            CurrentState  =  closedState;
        }


        
private  State CurrentState;
        
        
public   void  SetState(BottleStateSetting newState)
        
{
            
if  (newState  ==  BottleStateSetting.Closed)
            
{
                CurrentState 
=  closedState;
            }

            
else  
            
{
                CurrentState 
=  openedState;
            }

        }


        
public   void  Pour()
        
{
            CurrentState.Pour();
        }
    
    }


      
///   <summary>
    
///     Summary description for Client.
    
///   </summary>

     public   class  Client
    
{
        
public   static   int  Main( string [] args)
        
{
            ContextColaBottle contextColaBottle 
=   new  ContextColaBottle();

            Console.WriteLine(
" initial state is closed " );

            Console.WriteLine(
" Now trying to pour " );
              contextColaBottle.Pour();

            Console.WriteLine(
" Open bottle " );
            contextColaBottle.SetState(ContextColaBottle.BottleStateSetting.Opened);

            Console.WriteLine(
" Try to pour again " );
            contextColaBottle.Pour();

            
return   0 ;
        }

    }

}


设计模式:关于State模式的一些需要注意的地方

这个模式使得软件可以在不同的state下面呈现出完全不同的特征

  • 不同的theme使得相同的元素呈现出不同的特点
  • 不同的state下面相同的操作产生不同的效果
  • 不同的状态对相同的信息产生不同的处理

这个模式使得操作的state逻辑更加的清楚,省去了无数的state判断,而state的扩展性和可维护性和执行效率也大幅度的上升。关于state,有如下几点要注意的地方:

  • 所有的state应该被一个类(State Manager Class)管理:

    state之间的跳转和转换是非常复杂的,有时一些state可能要跳转的目标state有几十个,这个时候我们需要一个管理类(State Manager )来统一的管理这些state的切换,例如目标state的初始化和申请跳转state的结束处理,以及一些state间共享数据的存储和处理。与其称这个Manager 为管理类,不如说是一个中间类,它实现了state之间的解隅,使得各个state之间不比知道target state的具体信息,而只要向Manager申请跳转就可以了。使得各个state的模块化更好,更加的灵活

  • 所有的state都应该从一个state基类继承:

    既然state要教给一个manager来管理,那么自然的,这些state都应该从一个父类继承下来,这样manager并不需要知道很多子类的信息,一个最单纯的manager只要只要管理一个这样的基类的指针就可以了。另外,我们还可以统一的把state的一些共有的属性放在这里

  • state应该实现为一个singleton:

    state并不需要总是被申请,这样可能会造成管理上的混乱,state资源的申请也不应该可以任意进行,事实上,state的申请权限应该只有 Manager才有,并且有且只有一次。在这样的情况下,state的构造函数似乎应该被声明为protected or private ,而Manager应该被声明为state的友元,但是友元被看成是破坏类的封装性的一种做法,这一点上,我很矛盾,所以在这一条上我只能采取一种漠视的态度。

  • 应该做一个state么?这是一个问题:

    state可以说是if-else的一种替代品,极端的情况下面state可以让你的程序中if-else程序块消失得无影无踪,但是,这并不是银弹。state对于状态可预知的情况下非常有效,但是对于state不可预知,或者相似的state数量太多。过多的state会造成class的粒度过细,程序反而不简洁。在这样的情况下,你应该考虑使用if-else程序块来替代state。

    例如:

    有这样的一个程序,它可以生成任意形状的多边形,而多边形的各个节点是可以移动的,问题就来了。

    我并不知道用户将要使用多少个节点的多边形,因此我无法的创建那么多相应的state来使得这样一个程序正常工作。state大多数都是确定的,对于不确定的,state似乎无能为力,例如此例

    一种解决方法是我利用Manager传递给state一个state参数,让state有机会知道用户的操作意图,在这个例子里面是让state知道用户打算操作某一个节点,而state根据这个state参数来处理用户的操作,比如说,state得到的是用户操作的某一个点的index ,而state只要写

    points[index].moveTo(points[index].getX()+offset_x , points[index].getY()+offset_y);

    就可以,从而避免了state过多出现的问题

对象的切换:

//  State pattern -- Structural example  


using  System;

namespace  DoFactory.GangOfFour.State.Structural
{
  
  
//  MainApp test application 

  
class  MainApp
  
{
    
static   void  Main()
    
{
      
//  Setup context in a state 
      Context c  =   new  Context( new  ConcreteStateA());

      
//  Issue requests, which toggles state 
      c.Request();
      c.Request();
      c.Request();
      c.Request();

      
//  Wait for user 
      Console.Read();
    }

  }


  
//  "State" 

  
abstract   class  State
  
{
    
public   abstract   void  Handle(Context context);
  }


  
//  "ConcreteStateA" 

  
class  ConcreteStateA : State
  
{
    
public   override   void  Handle(Context context)
    
{
      context.State 
=   new  ConcreteStateB();
    }

  }


  
//  "ConcreteStateB" 

  
class  ConcreteStateB : State
  
{
    
public   override   void  Handle(Context context)
    
{
      context.State 
=   new  ConcreteStateA();
    }

  }


  
//  "Context" 

  
class  Context
  
{
    
private  State state;

    
//  Constructor 
     public  Context(State state)
    
{
      
this .State  =  state;
    }


    
//  Property 
     public  State State
    
{
      
get return  state; }
      
set
      

        state 
=  value; 
        Console.WriteLine(
" State:  "   +  
          state.GetType().Name);
      }

    }


    
public   void  Request()
    
{
      state.Handle(
this );
    }

  }

}
 

 

posted on 2006-01-03 16:15 梦在天涯 阅读(1096) 评论(2)  编辑 收藏 引用 所属分类: Design pattern

评论

# re: 模式设计c#--行为型--state 2006-04-25 14:33 梦在天涯

State模式与Strategy模式的区别时什么啊?,potian大侠帮忙。
首先,两者的意图是不同的。策略用来处理算法变化,而状态则是透明地处理状态变化。
造成混淆的原因可能是两者好像都能成为继承的替代。
策略主要处理算法变化的意思是算法可能是要变的,但是这种变化却是由用户来决定到底采用何种算法。这些算法之间一般来说没有状态变迁的问题,并且你总是从几个算法中间选取一个。策略最经典的用法是和observe一起组成MVC,其中V通过Observe观察M,而V通过strategy控制C.
策略使用的另一个最频繁的地方就是消除大量的Case或if else ,但是条件是这些case中每个条件可以归纳为一个算法,最好它们只需要相同的参数。当然,在strategy中,Context可以提供接口让strategy,但是我一般不太喜欢这么用,因为这样可能造成一系列的不必要耦合和开销。
对这些case,if else使得strategy有了一个policy的别名,还有一个常用的地方叫做validator,譬如在输入框内进行检查时可以把它实现为Validator。有时候,if else的嵌套层次可能很深,这时候策略可能不能用,那么你可能需要更加复杂或者更加专注的Rule模式。
状态模式则有所不同,她实现的一个概念可以叫做动态继承,也就是继承的子类(每一个状态)可以发生变化。这些状态的变化是一个整体,组成了一个状态变化图。而一般来说,使用该模式的状态之间存在着一种线性变化的关系,也就是一个状态变为另一个,然后是第三个。客户代码并不清楚这些状态在何时发生变化,这样做的好处是在组成你整个变化过程中某些状态之间需要插入一个新的状态,或者状态的顺序之间发生变化,对客户是不可见。实现模式一方面,修改的也只是相领的状态。在处于不同的状态时,客户代码可以执行的方法也是不同的。但它的问题就是必须在Context和所有的状态实现所有状态可能的方法。
这两个之间的区别有时候可能没有,譬如在面向连结的TCPConnection例子中,不同的状态可能具有不同的方法。但是在我刚刚实现的一个无连结的P2P底层协议中,所有状态需要处理地就是一个processXML方法,这时候,你可以叫它状态或者策略都可以。但由于还是又状态变迁的问题,所以我喜欢把它叫做状态。  回复  更多评论   

# re: 模式设计c#--行为型--state 2006-04-30 18:39 cxvcx

zxcxzc  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

EMail:itech001#126.com

导航

统计

  • 随笔 - 461
  • 文章 - 4
  • 评论 - 746
  • 引用 - 0

常用链接

随笔分类

随笔档案

收藏夹

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

积分与排名

  • 积分 - 1795872
  • 排名 - 5

最新评论

阅读排行榜