注册

java设计模式:状态模式

定义

对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

优点

  1. 结构清晰,状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。
  2. 将状态转换显示化,减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
  3. 状态类职责明确,有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。

缺点

  1. 状态模式的使用必然会增加系统的类与对象的个数。
  2. 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
  3. 状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。

代码实现

状态模式包含以下主要角色。

  1. 环境类:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
  2. 抽象状态:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
  3. 具体状态:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
状态模式中,行为是由状态来决定的,不同状态下有不同行为。

举个例子把,比如电视,电视有2个状态,一个是开机,一个是关机,开机时可以切换频道,关机时切换频道不做任何响应。
public interface TvState{
public void nextChannerl();
public void prevChannerl();
public void turnUp();
public void turnDown();
}

public class PowerOffState implements TvState{
public void nextChannel(){}
public void prevChannel(){}
public void turnUp(){}
public void turnDown(){}

}


public class PowerOnState implements TvState{
public void nextChannel(){
System.out.println("下一频道");
}
public void prevChannel(){
System.out.println("上一频道");
}
public void turnUp(){
System.out.println("调高音量");
}
public void turnDown(){
System.out.println("调低音量");
}

}

public interface PowerController{
public void powerOn();
public void powerOff();
}

public class TvController implements PowerController{
TvState mTvState;
public void setTvState(TvStete tvState){
mTvState=tvState;
}
public void powerOn(){
setTvState(new PowerOnState());
System.out.println("开机啦");
}
public void powerOff(){
setTvState(new PowerOffState());
System.out.println("关机啦");
}
public void nextChannel(){
mTvState.nextChannel();
}
public void prevChannel(){
mTvState.prevChannel();
}
public void turnUp(){
mTvState.turnUp();
}
public void turnDown(){
mTvState.turnDown();
}

}


public class Client{
public static void main(String[] args){
TvController tvController=new TvController();
tvController.powerOn();
tvController.nextChannel();
tvController.turnUp();

tvController.powerOff();
//调高音量,此时不会生效
tvController.turnUp();
}


}

应用场景

通常在以下情况下可以考虑使用状态模式。
  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。

例子:

应用在已登录状态,点击评论,会正常弹出评论框,而未登录状态下,则是要跳转到登录界面登录后,再正常评论。

所以已登录和未登录状态下的评论行为是不同的,这个就可以用状态模式设计。

0 个评论

要回复文章请先登录注册