设计模式之状态模式

状态模式是一种行为型设计模式

当对象在不同的状态下会有不同的表现形式或者处理,那么这个时候可以使用状态模式来把复杂的判断的逻辑分散在各个类之中。

 

环境类(Context):  定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义初始状态。

抽象状态类(State):  定义一个接口以封装与Context的一个特定状态相关的行为。

具体状态类(ConcreteState):  每一子类实现一个与Context的一个状态相关的行为。

 

实例(Example):电梯在不同的运行状态下门的开关控制、手机账户在不同的信用级别可以欠费的额度不同、游戏中Boss在不同的状态下的属性不同

 

类图:

实例代码:

IRoom:接口定义规范行为

 interface IRoom
    {
        void CheckIn();
        void CheckOut();
        void Unsubscribe();
        void Book();
    }

Room:含有一个房间状态

  public class Room : IRoom
    {
        public RoomState State { get; set; }

        public Room()
        {
            State = new FreeState(this);
        }


        #region IRoom

        public void CheckIn()
        {
            State.CheckIn();
        }

        public void CheckOut()
        {
            State.CheckOut();
        }

        public void Unsubscribe()
        {
            State.Unsubscribe();
        }

        public void Book()
        {
            State.Book();
        }

        #endregion
    }

RoomState:定义房间状态的共同行为的抽象类

 public abstract class RoomState : IRoom
    {
        protected Room RoomManagement;

        protected RoomState(Room room)
        {
            RoomManagement = room;
        }

        #region IRoom

        public abstract void CheckIn();

        public abstract void CheckOut();

        public abstract void Unsubscribe();

        public abstract void Book();

        #endregion
    }

FreeState:空闲状态

 class FreeState : RoomState
    {
        public FreeState(Room room)
            : base(room)
        {
        }

        public override void CheckIn()
        {
            Console.WriteLine("空闲状态不能入住");
        }

        public override void CheckOut()
        {
            Console.WriteLine("空闲状态不能退房");
        }

        public override void Unsubscribe()
        {
            Console.WriteLine("空闲状态不能取消预约");
        }

        public override void Book()
        {
            RoomManagement.State = new BookedState(RoomManagement);
            Console.WriteLine("预约成功");
        }
    }

BookedState:预订状态

  class BookedState : RoomState
    {
        public BookedState(Room room)
            : base(room)
        {
        }

        public override void CheckIn()
        {
            RoomManagement.State = new CheckInState(RoomManagement);
            Console.WriteLine("入住成功");
        }

        public override void CheckOut()
        {
            Console.WriteLine("预约状态不能退房");
        }

        public override void Unsubscribe()
        {
            RoomManagement.State = new FreeState(RoomManagement);
            Console.WriteLine("取消预约成功");
        }

        public override void Book()
        {
            Console.WriteLine("已经预约不能再次预约");
        }
    }

 CheckInState:入住状态

  class CheckInState : RoomState
    {
        public CheckInState(Room room)
            : base(room)
        {
        }

        public override void CheckIn()
        {
            Console.WriteLine("已经入住了");
        }

        public override void CheckOut()
        {
            RoomManagement.State = new FreeState(RoomManagement);
            Console.WriteLine("退房成功");
        }

        public override void Unsubscribe()
        {
            Console.WriteLine("入住状态不能取消预约");
        }

        public override void Book()
        {
            Console.WriteLine("入住状态不能预约");
        }
    }

 Client调用

  static void Main(string[] args)
        {
            Console.WriteLine("I.入住");
            Console.WriteLine("O.退房");
            Console.WriteLine("B.预约");
            Console.WriteLine("U.取消预约");

            var room = new Room();
            ConsoleKey key = ConsoleKey.A;
            while (key != ConsoleKey.Escape)
            {
                key = Console.ReadKey(false).Key;
                switch (key)
                {
                    case ConsoleKey.I:
                        room.CheckIn();
                        break;
                    case ConsoleKey.O:
                        room.CheckOut();
                        break;
                    case ConsoleKey.B:
                        room.Book();
                        break;
                    case ConsoleKey.U:
                        room.Unsubscribe();
                        break;
                    default:
                        room.Book();
                        break;
                }
            }
        }
    }

运行结果:

优点:将不同状态下的处理分散到各个子类当中,避免了耦合,避免了过多的判断

缺点:状态过多的话,会产生很多子类,增加子类的复杂度

 

posted @ 2016-01-18 17:51  蘑菇mr  阅读(215)  评论(0编辑  收藏  举报