关键词搜索

源码搜索 ×
×

设计模式:状态模式(State)

发布2016-04-25浏览7676次

详情内容


欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。


欢迎跳转到本文的原文链接:https://honeypps.com/design_pattern/state/

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
这里写图片描述

状态模式的角色

  1. 环境角色Context):也称上下文,定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
  2. 抽象状态角色(State):定义一个接口,用以封装环境对象的一个特定的状态所对应的行为。
  3. 具体状态角色(ConcreteState):每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。

案例
以酒店订房为例,房间的状态有:空闲、预订、入住。那么空闲房间的状态可以转变为:预订、入住。已预订状态房间的状态可以转变为:入住、取消预订。已入住房间的状态可以转变为:退房
1 状态接口State

public interface State
{
    public void bookRoom();
    public void unsubscribeRoom();
    public void checkInRoom();
    public void checkOutRoom();
}

    2 房间类Room(环境角色)

    public class Room
    {
        private State freeTimeState;
        private State checkInState;
        private State bookedState;
    
        private State state;
    
        public Room()
        {
            freeTimeState = new FreeTimeState(this);
            checkInState = new CheckInState(this);
            bookedState = new BookedState(this);
            state = freeTimeState;
        }
    
        public void bookRoom()
        {
            state.bookRoom();
        }
        public void unsubscribeRoom()
        {
            state.unsubscribeRoom();
        }
        public void checkInRoom()
        {
            state.checkInRoom();
        }
        public void checkOutRoom()
        {
            state.checkOutRoom();
        }
    
        public String toString()
        {
            return "该房间的状态是:"+getState().getClass().getName();
        }
    
        public State getFreeTimeState()
        {
            return freeTimeState;
        }
    
        public void setFreeTimeState(State freeTimeState)
        {
            this.freeTimeState = freeTimeState;
        }
    
        public State getCheckInState()
        {
            return checkInState;
        }
    
        public void setCheckInState(State checkInState)
        {
            this.checkInState = checkInState;
        }
    
        public State getBookedState()
        {
            return bookedState;
        }
    
        public void setBookedState(State bookedState)
        {
            this.bookedState = bookedState;
        }
    
        public State getState()
        {
            return state;
        }
    
        public void setState(State state)
        {
            this.state = state;
        }
    }
    
      8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    3 房间状态(具体状态角色)
    空闲状态

    public class FreeTimeState implements State
    {
        private Room hotelManagement;
    
        public FreeTimeState(Room hotelManagement)
        {
            this.hotelManagement = hotelManagement;
        }
        @Override
        public void bookRoom()
        {
            System.out.println("您已经预定成功了!");
            this.hotelManagement.setState(this.hotelManagement.getBookedState());
        }
    
        @Override
        public void unsubscribeRoom()
        {
        }
    
        @Override
        public void checkInRoom()
        {
            System.out.println("您已经入住了!");
            this.hotelManagement.setState(this.hotelManagement.getCheckInState());
        }
    
        @Override
        public void checkOutRoom()
        {
        }
    }
    
      8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    入住状态

    public class CheckInState implements State
    {
        private Room hotelManagement;
    
        public CheckInState(Room hotelManagement)
        {
            this.hotelManagement = hotelManagement;
        }
        @Override
        public void bookRoom()
        {
            System.out.println("该房间已经入住了");
        }
    
        @Override
        public void unsubscribeRoom()
        {
        }
    
        @Override
        public void checkInRoom()
        {
            System.out.println("该房间已经入住了");
        }
    
        @Override
        public void checkOutRoom()
        {
            System.out.println("退房成功");
            this.hotelManagement.setState(this.hotelManagement.getFreeTimeState());
        }
    }
    
      8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    预订状态

    public class BookedState implements State
    {
        private Room hotelManagement;
    
        public BookedState(Room hotelManagement)
        {
            this.hotelManagement = hotelManagement;
        }
    
        @Override
        public void bookRoom()
        {
            System.out.println("该房间已经预定了");
        }
    
        @Override
        public void unsubscribeRoom()
        {
            System.out.println("成功退订");
            this.hotelManagement.setState(this.hotelManagement.getFreeTimeState());
        }
    
        @Override
        public void checkInRoom()
        {
            System.out.println("入住成功");
            this.hotelManagement.setState(this.hotelManagement.getCheckInState());
        }
    
        @Override
        public void checkOutRoom()
        {
        }
    }
    
      8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    4 测试代码

            Room[] rooms = new Room[2];
            for(int i=0;i<rooms.length;i++)
            {
                rooms[i] = new Room();
            }
    
            rooms[0].bookRoom();
            rooms[0].checkInRoom();
            rooms[0].bookRoom();
            System.out.println(rooms[0]);
            System.out.println("-------------");
    
            rooms[1].checkInRoom();
            rooms[1].bookRoom();
            rooms[1].checkOutRoom();
            rooms[1].bookRoom();
            System.out.println(rooms[1]);
    
      8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    输出:

    您已经预定成功了!
    入住成功
    该房间已经入住了
    该房间的状态是:design.state.CheckInState
    -------------
    您已经入住了!
    该房间已经入住了
    退房成功
    您已经预定成功了!
    该房间的状态是:design.state.BookedState
    
      8
    • 9
    • 10

    优缺点
    优点:

    1. 封装了转换规则。
    2. 枚举可能的状态,在枚举状态之前需要确定状态种类。
    3. 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
    4. 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
      缺点:
    5. 状态模式的使用必然会增加系统类的对象的个数
    6. 状态模式的结构与实现都较为复杂,如果使用不当讲导致程序结构和代码的混乱。
    7. 状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

    适用场景

    1. 对象的行为依赖于它的状态(属性)并且可以根据它的状态而改变它的相关行为
    2. 代码中包含大量与对象状态相关的条件语句

    JDK中的状态模式
    java.util.Iterator
    javax.faces.lifecycle.LifeCycle#execute()


    欢迎跳转到本文的原文链接:https://honeypps.com/design_pattern/state/

    参考资料

    1. 23种设计模式
    2. 细数JDK里的设计模式
    3. 设计模式读书笔记—–状态模式

    欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。


    相关技术文章

    点击QQ咨询
    开通会员
    返回顶部
    ×
    微信扫码支付
    微信扫码支付
    确定支付下载
    请使用微信描二维码支付
    ×

    提示信息

    ×

    选择支付方式

    • 微信支付
    • 支付宝付款
    确定支付下载