本文已参与[新人创作礼]活动,一起开启掘金创作之路
1. 概念
对有状态的对象,把复杂的"判断逻辑"提取到不同的状态对象中,允许状态对象在其内部发生改变时改变其行为。 状态模式是一种对象行为型模式。
2. 优点
- 结构清晰,状态模式将于特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足"单一职责原则"。
- 将状态转换显示化,减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
- 状态类职责明确,有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。
3. 缺点
- 状态模式的使用必然会增加系统的类与对象的个数。
- 状态模式的结构与实现都较为复杂,如果使用不当会道之程序结构和代码的混乱。
- 状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改哪些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。
4. 结构与实现
状态模式把受环境改变的对象行为包装在不同的状态对象里,其意图是让一个对象在其内部状态改变的时候,其行为也随之改变。
4.1 结构
主要角色:
- 环境类角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。
- 抽象状态角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
- 具体状态角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。
4.2 实现
//环境类
public class Context {
private State state;
public Context() {
this.state = new Weiding();
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void handle() {
state.handle(this);
}
}
//抽象状态类
public abstract class State {
public abstract void handle(Context context);
}
//具体状态 我也不知道我心情咋样
public class Weiding extends State {
@Override
public void handle(Context context) {
System.out.println("早上刚起床,我也不知道我心情咋样");
double tianqi = Math.random();
System.out.println(tianqi);
if (tianqi > 0.7) {
System.out.println("推开窗,阳光明媚,心情好");
context.setState(new Kaixin());
} else if (tianqi > 0.4) {
System.out.println("下雨了,心情不好了");
context.setState(new Shangxin());
} else {
System.out.println("心情无变化");
}
}
}
//具体状态 开心
public class Kaixin extends State {
@Override
public void handle(Context context) {
System.out.println("今天很开心");
double tianqi = Math.random();
System.out.println(tianqi);
if (tianqi > 0.7) {
System.out.println("没出门,心情不知道咋样");
context.setState(new Weiding());
} else if (tianqi > 0.4) {
System.out.println("下雨了,心情不好了");
context.setState(new Shangxin());
} else {
System.out.println("心情无变化");
}
}
}
//具体状态 伤心
public class Shangxin extends State {
@Override
public void handle(Context context) {
System.out.println("今天很伤心");
double tianqi = Math.random();
System.out.println(tianqi);
if (tianqi > 0.7) {
System.out.println("推开窗,阳光明媚,心情好");
context.setState(new Kaixin());
} else if (tianqi > 0.4) {
System.out.println("没出门,不知道心情咋样");
context.setState(new Weiding());
} else {
System.out.println("心情无变化");
}
}
}
测试
public class StateTest {
@Test
public void test1() {
Context context = new Context();
for (int i = 0; i < 3; i++) {
context.handle();
}
}
}