由于blog各种垃圾评论太多,而且本人审核评论周期较长,所以懒得管理评论了,就把评论功能关闭,有问题可以直接qq骚扰我

设计模式—状态模式

JAVA 西门飞冰 936℃
[隐藏]

1.定义

状态模式:它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换

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

2.状态模式结构

image-20221003095640707

3.代码示例

需求:视频网站有着会员和很多视频,会员又分为三级,普通会员,vip会员,未登陆会员,这三种角色其实就对应了三种不同的状态

会员用户状态抽象类:

public abstract class UserState {
    public UserState(User user) {
        this.user = user;
    }
    // 内部持有的User对象是上下文,操作的目标
    protected User user;

    public void setUser(User user) {
        this.user = user;
    }

    // 不同会员用户播放的视频种类不同
    public abstract void play4K();
    public abstract void play720P();
    public abstract void play1080P();

}

未登陆会员状态的实现:

public class GuestState extends UserState {
    // 构造方法从外侧传入User对象
    public GuestState(User user) {
        super(user);
    }

    @Override
    public void play4K() {
        throw new RuntimeException("游客禁止播放4K视频");
    }

    @Override
    public void play720P() {
        System.out.println(user.getUname() + "正在播放720P视频");
    }

    @Override
    public void play1080P() {
        throw new RuntimeException("游客禁止播放1080P视频");
    }
}

普通会员状态的实现:

public class MemberState extends UserState {
    public MemberState(User user) {
        super(user);
    }

    @Override
    public void play4K() {
        throw new RuntimeException("普通会员禁止播放4K视频");
    }

    @Override
    public void play720P() {
        System.out.println(user.getUname() + "正在播放720P视频");
    }

    @Override
    public void play1080P() {
        System.out.println(user.getUname() + "正在播放1080P视频");
    }
}

VIP会员状态的实现:

public class VipState extends UserState {
    public VipState(User user) {
        super(user);
    }

    @Override
    public void play4K() {
        System.out.println(user.getUname() + "正在播放4K视频");
    }

    @Override
    public void play720P() {
        System.out.println(user.getUname() + "正在播放720P视频");
    }

    @Override
    public void play1080P() {
        System.out.println(user.getUname() + "正在播放1080P视频");
    }
}

上下文对象:

public class User {
    // 上下文对象要持有状态的应用,并传递调用不同的状态动态
    private UserState userState;
    private String uname;
    // 默认是游客状态
    public User(String uname) {
        this.uname = uname;
        this.userState = new GuestState(this);
        //this.userState.setUser(this);
    }

    public String getUname() {
        return uname;
    }
    //改变状态为普通会员
    public void registe(){
        this.userState = new MemberState(this);
        //this.userState.setUser(this);
    }
    // 改变状态为VIP会员
    public void openVIP(){
        this.userState = new VipState(this);
        //this.userState.setUser(this);
    }

    public void play4K() {
        userState.play4K();
    }

    public void play720P() {
        userState.play720P();
    }

    public void play1080P() {
        userState.play1080P();
    }
}

客户端:只需要关注上下⽂的操作,内部变化交给State实现即可。

public class Client {
    public static void main(String[] args) {
        User user = new User("Hello树先生");
        user.play720P();
        user.registe();
        user.play1080P();
        user.openVIP();
        user.play4K();
    }
}

4.优点

代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中

将所有与某个状态有关的⾏为放到⼀个类中,并且可以⽅便地增加新的状态,只需要改变对象状态即可改变对象的⾏为。

5.缺点

状态模式的使⽤必然会增加系统类和对象的个数。

状态模式对”开闭原则”的⽀持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则⽆法切换到新增状态,⽽且修改某个状态类的⾏为也需修改对应类的源代码。

6.状态模式使用场景

代码中包含⼤量与对象状态有关的条件语句,可消除⼤量的if…else…判断,将其剥离为⼀个个状态。

转载请注明:西门飞冰的博客 » 设计模式—状态模式

喜欢 (0)or分享 (0)