目录
1.核心思想
将行为内部状态和行为关联起来,在内部状态发生改变的时候,行为也随之改变。
我们的电脑有开机,关机,待机。我们只需要操作代码是computer.state的方法,当我们电脑从开机到关机,内部状态发生改变的时候,同样一个方法,可以表现他的不同行为。
2.成员
Context(上下文):
持有一个状态对象的引用,并且可以在运行时改变它。
在状态对象中委托行为。
State(状态):
定义一个接口,用于封装与上下文的一个特定状态相关的行为。
ConcreteState(具体状态):
实现了状态接口的具体状态类,封装了与该状态相关的具体行为。
3.优点(第六个最重要)
1.简化代码结构
-
减少条件判断:状态模式通过将不同状态的行为封装在具体的状态类中,减少了上下文类中的条件判断(如
if-else
或switch
语句)。这使得上下文类的代码更简洁、易于维护。 -
集中状态逻辑:将每个状态的行为集中到一个类中,使得每个状态的处理逻辑更集中,代码更易于理解和管理。
2. 提高系统的灵活性和可扩展性
-
状态扩展:添加新状态只需创建新的状态类,而不需要修改已有的状态类和上下文类。系统可以在运行时动态地切换状态,适应不同的需求和场景。
-
行为变化:通过状态对象的切换,系统可以轻松地改变对象的行为。这种行为变化是透明的,不需要在上下文类中编写复杂的状态转换逻辑。
3. 符合开闭原则
-
开闭原则:状态模式符合开闭原则,即对扩展开放,对修改关闭。新状态的添加不会影响到现有的状态类和上下文类,只需新增状态类即可。这使得系统在扩展功能时更加灵活和稳定。
4. 提高代码的可维护性
-
分离关注点:每个状态类封装了与特定状态相关的行为,使得代码结构更加清晰。这样,开发人员可以在修改或调试状态逻辑时,不会影响到其他状态的实现。
-
易于理解和调试:状态模式使得状态变化和行为逻辑更加直观,开发人员可以更容易地理解和调试状态相关的代码。
5. 增强系统的可测试性
-
单元测试:由于状态逻辑被封装在独立的状态类中,单元测试变得更加容易。可以针对每个具体状态类进行测试,而不需要测试整个上下文类。
-
状态转换测试:测试状态模式时,可以专注于状态之间的转换逻辑,确保每个状态在转换时表现出预期的行为。
6. 支持对象的行为在运行时改变
-
动态行为改变:状态模式允许对象在运行时根据其内部状态的变化来改变行为。这使得系统能够根据不同的状态表现出不同的行为,而不需要在代码中进行硬编码。
4.代码实现
4.1 状态接口
//状态接口
public interface ComputerState {
void pressPowerButton(Computer computer);
}
4.2 具体状态类
//具体状态类
public class PoweredOnState implements ComputerState {
@Override
public void pressPowerButton(Computer computer) {
System.out.println("电脑已经开机");
computer.setState(new StandbyState());
}
}
//具体状态类
public class StandbyState implements ComputerState {
@Override
public void pressPowerButton(Computer computer) {
System.out.println("电脑处于待机状态");
computer.setState(new PoweredOffState());
}
}
//具体状态类
public class PoweredOffState implements ComputerState {
@Override
public void pressPowerButton(Computer computer) {
System.out.println("待机时间过长,电脑没电将要关机");
System.out.println("最终状态:关机");
}
}
4.3 上下文类
//上下文类
public class Computer {
private ComputerState state;
public Computer(ComputerState initialState) {
this.state = initialState;
}
public void setState(ComputerState state) {
this.state = state;
}
public void pressPowerButton() {
state.pressPowerButton(this);
}
}
4.4 测试类
public class Test {
public static void main(String[] args) {
//初始动作为开机
Computer computer = new Computer(new PoweredOnState());
computer.pressPowerButton();
computer.pressPowerButton();
computer.pressPowerButton();
}
}