introduction:
状态模式:
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
该模式将状态封装成独立的类,并将动作委托到代表当前状态的对象,我们知道行为会随着内部状态而改变。
通过组合简单引用不同的状态对象来造成类改变的假象。
状态模式是不想在context中放置许多条件判断的替代方案。
通过将行为包装进状态对象中,你可以通过在context内简单地改变状态对象来改变context的行为。
一般来说,状态的转换是固定的时候,就适合放在context中,然而,当转换是更动态的时候,通常就会放在状态类中。
将状态转换放在状态类中的缺点是:状态类之间产生了依赖。我们在Context类中使用getter方法,将依赖减到最小,而不是显式硬编码具体状态类。
Context内部有许多实例,这些实例之间可以共享状态对象,这样做的前台就是状态对象不能持有它们自己的内部状态,否则就不能共享。
如果状态需要利用Context中的方法或者实例变量,必须在每一个方法中传入一个context引用。
虽然状态模式总是增加许多类,但是这样做就可以省略大量的整块条件语句,这会让代码利于维护和理解。
状态模式允许一个内部状态而拥有不同的行为。
状态模式用类代表状态。
Context类会将行为委托给当前状态对象。
通过将每个状态封装进一个类,我们把需要做的任何改变局部化了。
状态模式允许Context随着状态的改变而改变行为。
状态转换可以由State类或Context类控制。
使用状态类通常会导致设计类中的数目大量增加。
状态类可以被多个Context实例共享。
demo:使用状态模式模拟web容器的状态。对于web容器来说,存在打开和关闭两种状态,对于这两种状态,我们存在三种操作:打开,刷新,关闭。现在我们把web容器的状态封装为一个类,所有状态类继承State接口,用户通过操作web容器上下文,可以间接操作状态的行为。
State.java
public abstract class State {
public void open(){
throw new UnsupportedOperationException();
}
public void refresh(){
throw new UnsupportedOperationException();
}
public void close(){
throw new UnsupportedOperationException();
}
}
CloseState.java
public class CloseState extends State{
private Context context;
public CloseState(Context context) {
this.context = context;
}
@Override
public void open() {
System.out.println("容器打开了");
context.setState(context.getOpenState());
}
@Override
public void close() {
System.out.println("容器目前是关闭状态,不能关闭");
}
}
OpenState.java
public class OpenState extends State{
private Context context;
public OpenState(Context context) {
this.context = context;
}
@Override
public void open() {
System.out.println("容器目前属于打开状态,不能打开");
}
@Override
public void refresh() {
System.out.println("容器被刷新了");
context.setState(context.getOpenState());
}
@Override
public void close() {
System.out.println("容器关闭了");
context.setState(context.getCloseState());
}
}
Context.java
public class Context {
private State closeState;
private State openState;
private State state = closeState;
/**
* 用于标识当前系统状态0--关闭,1--打开
*/
private Integer type = 0;
public Context(){}
public Context(Integer type){
closeState = new CloseState(this);
openState = new OpenState(this);
this.type = type;
if(this.type.equals(1)){
state = openState;
}else{
state = closeState;
}
}
public State getCloseState() {
return closeState;
}
public void setCloseState(State closeState) {
this.closeState = closeState;
}
public State getOpenState() {
return openState;
}
public void setOpenState(State openState) {
this.openState = openState;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void open(){
state.open();
}
public void refresh(){
state.refresh();
}
public void close(){
state.close();
}
}
Test.java
public class Test {
public static void main(String[] args) {
//初始化 设置容器状态
Context context = new Context(0);
//一系列操作容器的操作(可能存在不合法操作)
context.close();
context.open();
context.open();
context.refresh();
context.close();
context.close();
}
}
输出结果:
容器目前是关闭状态,不能关闭
容器打开了
容器目前属于打开状态,不能打开
容器被刷新了
容器关闭了
容器目前是关闭状态,不能关闭
总而言之,状态模式是使用Class取代一个java类中复杂的选择结构,是代码易于维护,用户通过操作Context类,变相的操作State的内部方法。