今天咱们讲的是状态模式【State Pattern】、这个名字咋一看很差理解,可是仔细一想仍是比较容易的。状态模式重点关注的是状态。状态又牵扯着什么呢?房屋的状态暂且能够分为出租、签定合同、退房。那么出租对应的是什么呢?出租状态表明能够租房。能够租房是一个行为了。因此不难理解的是状态模式关注的是状态的改变与行为的变化。设计模式
在软件系统中,常常状态的改变影响着行为的变化。例如房屋状态是出租既能够租房、出售既能够买卖房、不租售意味不可操做。那么如何避免对象操做和状态转换之间出现紧耦合呢?状态模式将每种状态对应的行为抽象出来成为单独新的对象,这样状态的变化再也不依赖于对象内部的行为正解决了此问题。bash
容许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。ui
咱们看下案例图中主要三个部分:this
环境角色:包含保留了一个具体状态的实例、给出当前状态及调用方法。spa
抽象状态:定义接口、封装一个状态相对应的行为方法。设计
具体状态:实现具体状态对应的的具体对应行为。code
咱们继续看这个房屋的案例,针对房屋咱们整理这么一个案例,租房而后签定合同。合同半年内退房无押金。租房时间达到半年退房可得押金。咱们看下代码实现吧:cdn
namespace State_Pattern
{
/// <summary>
/// 房屋对象类
/// </summary>
public class StatePattern
{
/// <summary>
/// 房屋Id
/// </summary>
public int Id { get; set; }
/// <summary>
/// 房屋名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 租房时间/月
/// </summary>
public int Time { get; set; }
/// <summary>
/// 房屋状态
/// </summary>
public HouseState State { get; set; }
/// <summary>
/// 是否退押金
/// </summary>
public bool IsDeposit { get; set; }
}
/// <summary>
/// 房屋出租状态枚举
/// </summary>
public enum HouseState
{
[Description("出租")]
Lease =1,
[Description("签定合同")]
Leaseed = 2,
[Description("退房")]
Deposit = 3,
}
/// <summary>
/// 环境角色
/// </summary>
public class Environmental
{
public State _state;
/// <summary>
/// 初始化房屋状态
/// </summary>
public Environmental()
{
this._state = new LeaseState();
}
public StatePattern _statePattern { get; set; }
/// <summary>
/// 获取房屋对象
/// </summary>
/// <param name="statePattern"></param>
public void GetStatePattern(StatePattern statePattern,State state=null)
{
_statePattern = statePattern;
if (state!=null)
{
_state = state;
}
}
/// <summary>
/// 更改状态方法
/// </summary>
/// <param name="state"></param>
public void SetState(State state)
{
_state = state;
}
public void Show()
{
if (this._statePattern!=null)
{
_state.Handle(this);
}
else
{
Console.WriteLine("无可操做房屋!");
}
}
}
/// <summary>
/// 抽象状态接口
/// </summary>
public interface State
{
void Handle(Environmental environmental);
}
/// <summary>
/// 出租状态
/// </summary>
public class LeaseState : State
{
public void Handle(Environmental environmental)
{
//房屋出租
if (environmental._statePattern.State==HouseState.Lease)
{
Console.WriteLine($"{environmental._statePattern.Name}房屋正在出租!");
Console.WriteLine("若是以为能够的话就签定租房合同!");
environmental.SetState(new LeaseedState());
environmental.Show();
}
}
}
/// <summary>
/// 签定合同状态
/// </summary>
public class LeaseedState : State
{
public void Handle(Environmental environmental)
{
//后期办理退房手续
if (environmental._statePattern.State == HouseState.Lease)
{
Console.WriteLine($"{environmental._statePattern.Name}签定租房合同!");
environmental._statePattern.State = HouseState.Leaseed;
environmental._statePattern.Time = 1;
environmental.SetState(new DepositState());
environmental.Show();
}
}
}
/// <summary>
/// 退房有押金状态
/// </summary>
public class DepositState : State
{
public void Handle(Environmental environmental)
{
environmental._statePattern.IsDeposit = true;
if (environmental._statePattern.State == HouseState.Leaseed && environmental._statePattern.Time < 6)
{
Console.WriteLine($"{environmental._statePattern.Name}若是如今退房的话是不能退押金的!");
environmental._statePattern.IsDeposit = false;
}
else
Console.WriteLine($"{environmental._statePattern.Name}若是如今退房的话是能够退押金的!");
Console.WriteLine("考虑是否退房!");
}
}
}复制代码
namespace State_Pattern
{
class Program
{
static void Main(string[] args)
{
//初始化房源信息
List<StatePattern> statePatterns = new List<StatePattern>();
statePatterns.Add(new StatePattern {Id=1,Name="房屋一",State=HouseState.Lease });
Environmental environmental = new Environmental();
//房屋一出租
environmental.GetStatePattern(statePatterns.Where(x=>x.Id==1).FirstOrDefault());
environmental.Show();
//时间大于半年可退押金
statePatterns[0].Time = 7;
environmental.Show();
}
}
}复制代码
在上面的代码运行以后房屋一的状态在其对象内部发送了改变,从而行为也发送了变化。刚开始的正在出租改变成了签定合同出租以后。行为变化也从签定合同转变成了退房操做。 对象
一、行为随着状态改变而改变的场景。blog
二、条件或分支语句的替代者。
一、封装了状态及行为的转换规则。
二、在编写钱枚举出可能的状态,肯定状态的种类。
三、方便状态的增长。只须要改变状态便可改变对象的行为。扩展性好。
四、能够多个环境一块儿共享一个状态对象,减小了对象个数。
一、状态模式会增长系统类和对象的个数
二、对开闭原则不友好。增长状态须要对那些负责状态转换的代码进行修改。不然的话没法转换到最新的状态。
三、状态模式的结构和实现都比较复杂,使用不当容易形成代码混乱及难理解。
状态模式到这里介绍完了,状态模式模式注重的状态在内部的改变自动改变其行为。对象看起来好像改变了它的类同样。抓住重点实现。第一个是状态的变化。第二个是状态变化引发的行为变化。第三个是在状态内部改变的。把状态的转换逻辑和状态对象放在一块儿。继而替换一个庞大的语句条件。
时间抓起来讲是金子,抓不住就是流水。
欢迎你们扫描下方二维码,和我一块儿踏上设计模式的闯关之路吧!