状态模式(State Pattern)

状态模式(State Pattern)是一种行为设计模式,它允许对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。以下从多个方面详细介绍状态模式。

模式结构与角色

状态模式主要包含以下几个角色:

  1. 抽象状态(State):定义了一个接口,封装了与上下文的一个特定状态相关的行为。通常包含多个方法,这些方法对应着上下文在该状态下可能执行的操作。
  2. 具体状态(Concrete State):实现了抽象状态接口,每个具体状态类都封装了特定状态下的行为逻辑。当上下文的状态改变时,会委托给相应的具体状态类来处理。
  3. 上下文(Context):维护一个对抽象状态对象的引用,负责根据业务逻辑切换状态。上下文将请求委托给当前的状态对象来处理。

代码示例

以下是一个简单的状态模式示例,模拟一个电梯系统,电梯有开门、关门、运行、停止四种状态:

// 抽象状态
interface ElevatorState {
    void open();
    void close();
    void run();
    void stop();
}

// 具体状态:开门状态
class OpenState implements ElevatorState {
    private Elevator elevator;

    public OpenState(Elevator elevator) {
        this.elevator = elevator;
    }

    @Override
    public void open() {
        System.out.println("电梯已经开门,无需重复开门");
    }

    @Override
    public void close() {
        System.out.println("电梯门关闭");
        elevator.setState(elevator.getCloseState());
    }

    @Override
    public void run() {
        System.out.println("电梯门未关闭,不能运行");
    }

    @Override
    public void stop() {
        System.out.println("电梯已经开门,处于停止状态");
    }
}

// 具体状态:关门状态
class CloseState implements ElevatorState {
    private Elevator elevator;

    public CloseState(Elevator elevator) {
        this.elevator = elevator;
    }

    @Override
    public void open() {
        System.out.println("电梯门打开");
        elevator.setState(elevator.getOpenState());
    }

    @Override
    public void close() {
        System.out.println("电梯门已经关闭,无需重复关门");
    }

    @Override
    public void run() {
        System.out.println("电梯开始运行");
        elevator.setState(elevator.getRunState());
    }

    @Override
    public void stop() {
        System.out.println("电梯还未运行,无需停止");
    }
}

// 具体状态:运行状态
class RunState implements ElevatorState {
    private Elevator elevator;

    public RunState(Elevator elevator) {
        this.elevator = elevator;
    }

    @Override
    public void open() {
        System.out.println("电梯正在运行,不能开门");
    }

    @Override
    public void close() {
        System.out.println("电梯正在运行,门已经关闭");
    }

    @Override
    public void run() {
        System.out.println("电梯正在运行,无需重复启动");
    }

    @Override
    public void stop() {
        System.out.println("电梯停止运行");
        elevator.setState(elevator.getStopState());
    }
}

// 具体状态:停止状态
class StopState implements ElevatorState {
    private Elevator elevator;

    public StopState(Elevator elevator) {
        this.elevator = elevator;
    }

    @Override
    public void open() {
        System.out.println("电梯门打开");
        elevator.setState(elevator.getOpenState());
    }

    @Override
    public void close() {
        System.out.println("电梯门已经关闭,无需重复关门");
    }

    @Override
    public void run() {
        System.out.println("电梯开始运行");
        elevator.setState(elevator.getRunState());
    }

    @Override
    public void stop() {
        System.out.println("电梯已经停止,无需重复停止");
    }
}

// 上下文:电梯
class Elevator {
    private ElevatorState openState;
    private ElevatorState closeState;
    private ElevatorState runState;
    private ElevatorState stopState;
    private ElevatorState currentState;

    public Elevator() {
        openState = new OpenState(this);
        closeState = new CloseState(this);
        runState = new RunState(this);
        stopState = new StopState(this);
        currentState = closeState;
    }

    public ElevatorState getOpenState() {
        return openState;
    }

    public ElevatorState getCloseState() {
        return closeState;
    }

    public ElevatorState getRunState() {
        return runState;
    }

    public ElevatorState getStopState() {
        return stopState;
    }

    public void setState(ElevatorState state) {
        this.currentState = state;
    }

    public void open() {
        currentState.open();
    }

    public void close() {
        currentState.close();
    }

    public void run() {
        currentState.run();
    }

    public void stop() {
        currentState.stop();
    }
}

// 客户端代码
public class StatePatternExample {
    public static void main(String[] args) {
        Elevator elevator = new Elevator();

        elevator.open();
        elevator.close();
        elevator.run();
        elevator.stop();
        elevator.open();
    }
}

代码解释

  1. 抽象状态 ElevatorState:定义了电梯的四个操作方法 open()close()run()stop(),具体状态类需要实现这些方法。
  2. 具体状态类(OpenStateCloseStateRunStateStopState:实现了 ElevatorState 接口,每个类都封装了电梯在相应状态下的行为逻辑,并且在合适的操作后会改变电梯的状态。
  3. 上下文 Elevator:维护了四个具体状态对象的引用,以及当前的状态 currentState。通过 setState() 方法可以切换状态,并且将电梯的操作委托给当前状态对象来处理。
  4. 客户端代码:创建了电梯对象,并依次调用电梯的开门、关门、运行、停止和开门操作,观察电梯在不同状态下的行为。

优点

  1. 可维护性和可扩展性:将不同状态的行为封装在各自的具体状态类中,使得代码结构清晰,易于维护。当需要添加新的状态时,只需要创建新的具体状态类,符合开闭原则。
  2. 消除条件判断:避免了使用大量的 if - elseswitch - case 语句来处理不同状态的情况,使代码更加简洁和可读。
  3. 状态转换清晰:状态模式明确了状态之间的转换关系,每个状态类只负责自己状态下的行为和状态转换逻辑,使状态转换更加清晰和易于理解。

缺点

  1. 类的数量增加:随着状态的增加,具体状态类的数量也会增加,导致系统中的类数量增多,增加了系统的复杂度。
  2. 状态之间的耦合:如果状态之间的转换逻辑比较复杂,可能会导致具体状态类之间存在一定的耦合,影响代码的可维护性。

应用场景

  1. 工作流管理:在工作流系统中,任务可能有不同的状态(如待审批、已审批、已完成等),状态模式可以方便地管理任务在不同状态下的行为和状态转换。
  2. 游戏开发:游戏中的角色或物体可能有不同的状态(如站立、行走、攻击、防御等),使用状态模式可以实现角色在不同状态下的行为逻辑。
  3. 设备控制:对于一些复杂的设备,如电梯、自动售货机等,设备有不同的工作状态,状态模式可以有效地管理设备在不同状态下的操作和状态转换。
Java设计模式 文章被收录于专栏

设计模式是软件开发中针对反复出现的问题所总结归纳出的通用解决方案,它可以帮助开发者更高效地构建软件系统,提升代码的可维护性、可扩展性和可复用性。

全部评论

相关推荐

RAG 是啥?RAG,全称 Retrieval-Augmented Generation,意思是 “ 检索增强生成 ” 。以前的 AI 模型知识有限,还可能答错或者答得不靠谱,而且企业用起来也不安全。RAG 就是来解决这些问题的!它能让 AI 在回答前先去 “ 图书馆 ” (知识库)搜资料,再给出答案。RAG 怎么干活?RAG 的工作流程简单来说就是三步走:你问我答:用户问问题,比如 “ 今天吃什么好?”,RAG 系统接收到了。翻书找答案:RAG 的 “ 小助手 ” 会飞快地在知识库里找相关资料,比如美食推荐、营养搭配之类的。整合输出:把找到的资料和问题混合在一起,扔进大模型里加工,生成一个超棒的答案,比如 “ 今天你可以试试清蒸鲈鱼,肉嫩味美,还很营养哦!”。RAG 的核心组件RAG 主要有两个核心组件:检索器(Retriever):就像在图书馆里负责找书的管理员,能在知识库里快速定位到相关资料。生成器(Generator):拿到资料后,它就像个作家,把资料和问题结合,生成最终的回答。RAG 跟其他技术比有啥厉害之处?对比直接用大模型 API 或者微调,RAG 有这些牛 X 的地方:知识更新快:知识库能实时更新,AI 就能立马掌握新知识,不用重新训练,省时省力。省钱省心:不用大规模重新训练模型,成本大大降低。不会忘事儿:不会像微调那样,在没训练过的任务上表现不好,稳稳地保留了模型的通用能力。不过呢,RAG 也有点小缺点,比如在特别需要深度理解和风格模仿的问题上,可能就没微调那么厉害。RAG 的关键环节和挑战文档切分(Chunking):把文档切成合适的大小,就像切蛋糕一样,得找到那个完美的大小,不然可能影响检索效率。Embedding 模型选择:选对模型就像给汽车选发动机,直接决定向量表示的质量,影响后续的检索和生成效果。检索效果评估:得时刻监控检索的召回率和精确率,就像给检索系统做定期体检,有问题及时调整。向量数据库的作用:它是高效存储和检索向量表示的中流砥柱,就像给知识库装上了超级导航,能快速定位到相关信息。整体效果评估:要时不时对 RAG 系统来个全方位体检,从生成答案的准确性、相关性等方面打分,确保系统一直在线。
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务