设计模式14,状态模式、设计模式之间的关联和区别

目录

状态模式

设计模式之间的联系及区别

单例模式和工厂模式

单例模式和享元模式

外观模式和中介者模式

外观模式和单例模式

外观模式和抽象工厂模式

装饰者模式和代理模式

装饰者模式和适配器模式

适配器模式和外观模式

享元模式和代理模式

享元模式和单例模式

组合模式和访问者模式

桥接模式和组合模式

桥接模式和适配器模式

适配器模式和代理模式

模板方法模式和工厂方法模式

模板方法模式和策略模式

迭代器模式和访问者模式

策略模式和工厂模式

策略模式和状态模式

解释器模式和适配器模式

备忘录模式和状态模式

命令模式和备忘录模式

中介者模式和观察者模式

责任链模式和状态模式

访问者模式和迭代器模式

状态模式和享元模式


状态模式

允许一个对象在其内部状态改变时,改变他的行为。

类型:行为型

使用场景:一个对象存在多个状态(不同状态下行为不同),且状态可以互相转换时。例如电梯在上升或下降的时候不能开门,只有在电梯停在某一层的时候才可以开门。

优点:将不同的状态隔离。把各种状态的转换逻辑分不到State的子类中,减少相互间的依赖。增加新的状态比较简单。

缺点:在状态多的业务场景导致类数目增加,系统变得复杂。

例子:

public abstract class VideoState {
    protected VideoStateContext videoStateContext;

    public void setVideoStateContext(VideoStateContext videoStateContext) {
        this.videoStateContext = videoStateContext;
    }

    public abstract void play();
    public abstract void speed();
    public abstract void pause();
    public abstract void stop();
}
public class PlayState extends VideoState {
    @Override
    public void play() {
        System.out.println("正常播放视频");
    }

    @Override
    public void speed() {
        this.videoStateContext.setVideoState(VideoStateContext.SPEED_STATE);
    }

    @Override
    public void pause() {
        this.videoStateContext.setVideoState(VideoStateContext.PAUSE_STATE);
    }

    @Override
    public void stop() {
        this.videoStateContext.setVideoState(VideoStateContext.STOP_STATE);
    }
}
public class PauseState extends VideoState {
    @Override
    public void play() {
        this.videoStateContext.setVideoState(VideoStateContext.PLAY_STATE);
    }

    @Override
    public void speed() {
        this.videoStateContext.setVideoState(VideoStateContext.SPEED_STATE);
    }

    @Override
    public void pause() {
        System.out.println("暂停播放视频");
    }

    @Override
    public void stop() {
        this.videoStateContext.setVideoState(VideoStateContext.STOP_STATE);
    }
}
public class SpeedState extends VideoState {
    @Override
    public void play() {
        this.videoStateContext.setVideoState(VideoStateContext.PLAY_STATE);
    }

    @Override
    public void speed() {
        System.out.println("快进视频");
    }

    @Override
    public void pause() {
        this.videoStateContext.setVideoState(VideoStateContext.PAUSE_STATE);
    }

    @Override
    public void stop() {
        this.videoStateContext.setVideoState(VideoStateContext.STOP_STATE);
    }
}
public class StopState extends VideoState {
    @Override
    public void play() {
        this.videoStateContext.setVideoState(VideoStateContext.PLAY_STATE);
    }

    @Override
    public void speed() {
        System.out.println("ERROR 停止状态下无法快进");
    }

    @Override
    public void pause() {
        System.out.println("ERROR 停止状态下无法暂停");
    }

    @Override
    public void stop() {
        System.out.println("停止播放视频");
    }
}
public class VideoStateContext {
    private VideoState videoState;
    public final static PlayState PLAY_STATE = new PlayState();
    public final static SpeedState SPEED_STATE = new SpeedState();
    public final static PauseState PAUSE_STATE = new PauseState();
    public final static StopState STOP_STATE = new StopState();

    public VideoState getVideoState(){
        return videoState;
    }

    public void setVideoState(VideoState videoState) {
        this.videoState = videoState;
        this.videoState.setVideoStateContext(this);
    }

    public void play() {
        this.videoState.play();
    }

    public void speed() {
        this.videoState.speed();
    }

    public void pause() {
        this.videoState.pause();
    }

    public void stop() {
        this.videoState.stop();
    }
}
public class Test {
    public static void main(String[] args) {
        VideoStateContext videoStateContext = new VideoStateContext();
        videoStateContext.setVideoState(new PlayState());
        System.out.println("当前状态" + videoStateContext.getVideoState().getClass().getSimpleName());
        videoStateContext.pause();
        System.out.println("当前状态" + videoStateContext.getVideoState().getClass().getSimpleName());
        videoStateContext.speed();
        System.out.println("当前状态" + videoStateContext.getVideoState().getClass().getSimpleName());
        videoStateContext.stop();
        System.out.println("当前状态" + videoStateContext.getVideoState().getClass().getSimpleName());
        videoStateContext.pause();
        System.out.println("当前状态" + videoStateContext.getVideoState().getClass().getSimpleName());

    }
}

类图:

贯穿始终的就是上下文,每次的状态改变,也需要更改上下文中的状态。

用到设计模式的源码:

状态模式在框架中的运用比较少,多用于实际业务中。


设计模式之间的联系及区别

单例模式和工厂模式

在一些场景中,可以把一些工厂类设计成单例模式的。

单例模式和享元模式

一些业务场景中有很多单例对象,可以通过享元模式和单例模式的结合来完成单例对象的获取。这种情况下,享元模式的应用就相当于单例模式的工厂,只不过这个工厂的对象是已经创建好的。

外观模式和中介者模式

外观模式关注的是外界和子系统之间的交互,中介者模式关注的是子系统之间的交互。

外观模式和单例模式

通常可以把外观模式中的对象做成单例模式来使用。

外观模式和抽象工厂模式

外观类通过抽象工厂获取子系统的实例,这样子系统可以将内部对外观类独立。

装饰者模式和代理模式

装饰者模式注重在一个对象上动态的添加行为方法。代理模式注重控制对对象的访问,代理模式的代理类可以对客户隐藏对象的具体信息。通常在使用代理模式的时候,会在一个代理类中创建对象的实例,而对于装饰者模式,会把对象作为一个参数传给装饰者的构造器。

装饰者模式和适配器模式

他们都可以叫做包装模式。装饰者和被装饰者可以实现相同的接口,或者装饰者是被装饰者的子类。对于适配器模式,是配的类和被适配的类具有不同的接口。

适配器模式和外观模式

他们都是对现有类、现有系统的封装。外观模式定义了新的借口,适配器模式复用原有的接口。适配器模式使两个已有的接口协同工作,外观模式在现有的系统中提供一个更为方便的访问入口。如果强行把外观模式也叫适配器的话,二者适配粒度不同,外观模式用来适配整个子系统,外观所针对的对象粒度更大。

享元模式和代理模式

代理模式肯定是代理一个类,生成代理类需要花费的资源和时间会很多,那么就可以使用享元模式提高程序的处理速度。

享元模式和单例模式

关于容器单例,就是二者的结合。

组合模式和访问者模式

可以使用访问者模式访问组合模式中的递归结构。

桥接模式和组合模式

组合模式强调部分和整体的组合,而桥接模式强调平行级别上不同类的组合。

桥接模式和适配器模式

二者都是为了让两个系统配合工作。适配器模式会改变已有的接口,让他们之间相互配合。桥接模式是分离抽象和具体的实现,目的就是分离。适配器模式把功能上相似但接口不同的类适配起来,而桥接模式把类和抽象分离开,在此基础上是这些层次结构结合起来。

适配器模式和代理模式

适配器模式主要考虑改变对象的接口,代理模式不能改变所代理类的接口。

模板方法模式和工厂方法模式

工厂方法是模板方法的特殊实现。

模板方法模式和策略模式

他们都有封装算法。策略模式目的是使不同的算法可以相互替换,并且不影响应用层客户端的使用。模板方法模式针对定义一个算法的流程,将一些不太一样的具体实现步骤交给子类实现。模板方法模式不改变算法的流程,策略模式可以改变算法的流程,并且他们之间可以相互替换。

迭代器模式和访问者模式

二者都是迭代的访问集合对象中的元素。访问者模式扩展开放的是在访问时对对象的操作上,迭代器模式扩展开放的是在集合对象的种类上。

策略模式和工厂模式

工厂模式是创建型的,策略模式是行为型的。工厂模式接受指令,创建出符合要求的具体对象。策略模式接受已经创建好的对象,实现不同的行为。

策略模式和状态模式

策略模式在使用时,应用层需要知道使用哪个策略。状态模式在使用时,应用层不需要关心状态,这些状态会自动转换。一个目标有一个行为,对于这个行为有多种实现方式,使用策略模式。一个目标有多个状态,不同状态下行为有差异,且这些状态可以发生转换时,用状态模式。

解释器模式和适配器模式

适配器模式不需要预先知道适配的规则。解释器需要把规则写好,根据这些规则执行解释。

备忘录模式和状态模式

备忘录模式中会用实例表示状态,存档是对象的实例。对于状态模式,是一个类表示一个状态。

命令模式和备忘录模式

二者经常结合使用,可以使用备忘录模式保存命令。

中介者模式和观察者模式

二者可以结合使用。使用观察者模式实现中介者模式中角色间的通讯。

责任链模式和状态模式

责任链模式中每个对象并不知道下一个要处理的对象是谁,只有在应用层来设定链条的顺序。状态模式知道下一个对象是谁,在编译时就设定好。

访问者模式和迭代器模式

二者都是在某种数据结构上进行处理。访问者模式注重在保存在数据结构中的元素进行特定的处理,重点是处理。迭代器模式主要在于遍历保存在数据结构中的元素,重点是遍历。

状态模式和享元模式

二者可以配合使用。状态模式在没有对应的属性时,可以使用享元模式在多个上下文中共享这些对象的实例。

发布了97 篇原创文章 · 获赞 28 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/haozi_rou/article/details/104633796