首页 > 其他分享 >设计模式—状态模式

设计模式—状态模式

时间:2023-07-25 13:01:06浏览次数:32  
标签:状态 Context void 模式 context Override 设计模式 public

状态模式

目录

当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。

状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象 对应的类发生了改变一样。

优点

  • 结构清晰。避免了过多的switch...case或者if...else语句的使用, 避免了程序的复杂性,提高系统的可维护性 。
  • 遵循设计原则 。
  • 封装性非常好 。

缺点

子类会太多, 也就是类膨胀。

适用场景

  • 行为随状态改变而改变的场景。例如权限设计,人员的状态不同即使执行相同的行为结果也会不同, 在这种情况下需要考虑使用状态模式。
  • 条件、 分支判断语句的替代者。

注意事项

状态模式适用于当某个对象在它的状态发生改变时, 它的行为也随着发生比较大的变化, 也就是说在行为受状态约束的情况下可以使用状态模式, 而且使用时对象的状态最好不要超过5个。 —来源《设计模式之禅 第二版》

通用类图

classDiagram Context o.. State State <|-- ConcreteState class State{ +handle() } class Context{ +request() }

例子

电梯的开门、关门、运行、停止状态的变化

  • 上下文
/**
 * 上下文
 *
 * @author admin
 */
public class Context {
    //定义出所有的电梯状态
    public final static OpenningState OPENNING_STATE = new OpenningState();
    public final static ClosingState CLOSEING_STATE = new ClosingState();
    public final static RunningState RUNNING_STATE = new RunningState();
    public final static StoppingState STOPPING_STATE = new StoppingState();

    //定义一个当前电梯状态
    private LiftState liftState;

    public LiftState getLiftState() {
        return liftState;
    }

    public void setLiftState(LiftState liftState) {
        this.liftState = liftState;
        //把当前的环境通知到各个实现类中
        this.liftState.setContext(this);
    }

    public void open() {
        this.liftState.open();
    }

    public void close() {
        this.liftState.close();
    }

    //门开着时电梯就运行跑,这电梯,吓死你!
    public void run() {
        this.liftState.run();
    }

    public void stop() {
        this.liftState.stop();
    }
}
  • 抽象状态角色
/**
 * 抽象状态角色
 *
 * @author admin
 */
public abstract class LiftState {
    //定义一个环境角色, 也就是封装状态的变化引起的功能变化
    protected Context context;

    public void setContext(Context context) {
        this.context = context;
    }

    //首先电梯门开启动作
    public abstract void open();

    //电梯门有开启, 那当然也就有关闭了
    public abstract void close();

    //电梯要能上能下, 运行起来
    public abstract void run();

    //电梯还要能停下来
    public abstract void stop();
}
  • 开门状态
/**
 * 开门状态
 *
 * @author admin
 */
public class OpenningState extends LiftState {
    //开启当然可以关闭了, 我就想测试一下电梯门开关功能
    @Override
    public void close() {
        //状态修改
        super.context.setLiftState(Context.CLOSEING_STATE);
        //动作委托为CloseState来执行
        super.context.getLiftState().close();
    }

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

    @Override
    public void run() {
        //do nothing;
    }

    //开门还不停止?
    public void stop() {
        //do nothing;
    }
}
  • 关门状态
/**
 * 关闭状态
 *
 * @author admin
 */
public class ClosingState extends LiftState {
    //电梯门关闭, 这是关闭状态要实现的动作
    @Override
    public void close() {
        System.out.println("电梯门关闭...");
    }

    //电梯门关了再打开
    @Override
    public void open() {
        super.context.setLiftState(Context.OPENNING_STATE); //置为敞门状态
        super.context.getLiftState().open();
    }

    //电梯门关了就运行,这是再正常不过了
    @Override
    public void run() {
        super.context.setLiftState(Context.RUNNING_STATE); //设置为运行状态
        super.context.getLiftState().run();
    }

    //电梯门关着,我就不按楼层
    @Override
    public void stop() {
        super.context.setLiftState(Context.STOPPING_STATE); //设置为停止状态
        super.context.getLiftState().stop();
    }
}
  • 运行状态
/**
 * 运行状态
 *
 * @author admin
 */
public class RunningState extends LiftState {
    //电梯门关闭? 这是肯定的
    @Override
    public void close() {
        //do nothing
    }

    //运行的时候开电梯门?你疯了!电梯不会给你开的
    @Override
    public void open() {
        //do nothing
    }

    //这是在运行状态下要实现的方法
    @Override
    public void run() {
        System.out.println("电梯上下运行...");
    }

    //这绝对是合理的,只运行不停止还有谁敢坐这个电梯? !估计只有上帝了
    @Override
    public void stop() {
        //环境设置为停止状态
        super.context.setLiftState(Context.STOPPING_STATE);
        super.context.getLiftState().stop();
    }
}
  • 停止状态
/**
 * 关闭状态
 *
 * @author admin
 */
public class StoppingState extends LiftState {
    //停止状态关门? 电梯门本来就是关着的!
    @Override
    public void close() {
        //do nothing;
    }

    //停止状态,开门,那是要的!
    @Override
    public void open() {
        super.context.setLiftState(Context.OPENNING_STATE);
        super.context.getLiftState().open();
    }

    //停止状态再运行起来,正常得很
    @Override
    public void run() {
        super.context.setLiftState(Context.RUNNING_STATE);
        super.context.getLiftState().run();
    }

    //停止状态是怎么发生的呢?当然是停止方法执行了
    @Override
    public void stop() {
        System.out.println("电梯停止了...");
    }
}
  • 客户端
/**
 * 客户端
 *
 * @author admin
 */
public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        context.setLiftState(new ClosingState());
        context.open();
        context.close();
        context.run();
        context.stop();
    }
}
  • 运行结果

电梯门开启...
电梯门关闭...
电梯上下运行...
电梯停止了...

状态模式与策略模式的差异

状态模式通用类图

classDiagram Context o.. State : +state State <|-- ConcreteState class State{ +handle() } class Context{ +ContextInterface() +request() }

策略模式通用类图

classDiagram Context o.. Strategy : +strategy Strategy <|-- ConcreteStrategy class Strategy{ +AlgorithmInterface() } class Context{ +ContextInterface() }

区别:策略模式封装的是不同的算法, 算法之间没有交互, 以达到算法可以自由切换的目的; 而状态模式封装的是不同的状态, 以达到状态切换行为随之发生改变的目的。

标签:状态,Context,void,模式,context,Override,设计模式,public
From: https://www.cnblogs.com/kouhao/p/17579621.html

相关文章

  • 设计模式—中介者模式
    中介者模式目录中介者模式优点缺点适用场景中介者模式与外观模式差异用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。优点减少类之间的依赖,将原有的一对多的依赖变成一对一的依赖,同事类只依赖中......
  • 设计模式—单例模式
    目录优点缺点使用场景注意事项案例分析定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。优点由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁地创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。由......
  • 设计模式—命令模式
    命令模式目录命令模式命令模式与策略模式的差异:例子命令模式是一个高内聚的模式,其定义为:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。命令模式(CommandPattern)是一种数据驱动的设计模式,它属于行为......
  • 设计模式—解释器模式
    解释器模式解释器模式(InterpreterPattern)是一种按照规定语法进行解析的方案,在现在项目中使用较少,其定义如下:Givenalanguage,definearepresentationforitsgrammaralongwithaninterpreterthatusestherepresentationtointerpretsentencesinthelanguage。优......
  • 设计模式—门面模式
    门面模式门面模式(FacadePattern)也叫做外观模式,是一种比较常用的封装模式。要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。优点减少系统的相互依赖;提高了灵活性;提高安全性。缺点是不符合......
  • 设计模式—原型模式
    原型模式原型模式(PrototypePattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。优点原型模式是在内存二进制流的拷贝,要比直接new一个对象性......
  • 设计模式—工厂模式
    目录简单工厂模式类图案例分析工厂方法模式优点类图案例分析抽象工厂模式优点缺点使用场景注意事项类图案例分析工厂模式分为简单工厂模式,工厂方法模式,抽象工厂模式。简单工厂模式简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度......
  • vs c#判断程序是否调试模式,开发模式,发布模式,Debug模式,Release模式
    转发自:https://blog.csdn.net/qq_37664403/article/details/1187471951.Debug模式,Release模式#ifDEBUGConsole.WriteLine(“Debug模式”);#elseConsole.WriteLine(“Release模式”);#endif此方法适合习惯好的程序员,但是对我来说不怎么习惯使用,因为调试个代码,和不在调试情况下运......
  • Linux基础30 HTTP协议, 请求信息, 请求方法, 状态码, 请求头信息
    HTTP协议HTTP协议概述1.什么是HTTPHTTP全称:HyperTextTransferProtocol中文名:超文本传输协议HTTP协议简单的说,将用户请求的页面从服务器传输到客户端浏览器,浏览器进行解析,解析以后变成一个我们人类可以理解的方便观看的页面2.什么是超文本包含有超链接(Link)和......
  • 解决VS 2022使用Git无法显示文件状态图标问题
     在安装git插件之后,用vs2022打开打开项目时,项目文件夹不显示状态图标,解决如下:新建txt文件,将一下语句粘贴进去,然后将文件后缀名修改为cmd格式运行即可,如果第一次运行该文件一闪而过,可以多点几次REGADDHKEY_LOCAL_MACHINE\SOFTWARE\TEC\Ocular.3\agent\config/vhookapi_dis......