State模式的经典应用场景:订单处理(c#实现)
State模式在对象内部状态发生变化的时候,改变自身的行为,这通常是通过切换内部状态对象实现的,对象将自身在各个状态的行为推给了状态对象,从而解开了行为与对象的依赖。
场景描述
在经典的订单处理场景中,订单其不同状态的时候变现了不同的行为,具体内容如下:
- 假如订单是一个新创建的订单,那么它可以被寄送,也可以被取消;
- 假如订单已经被寄送,那么它不可以被再次寄送,也不可以被取消;
- 假如订单已经被取消,那么它不可以被寄送,也不可以被取消。
上述内容中详细解释了订单状态和对应行为的关系。
遇到问题
对逻辑的第一映像,通常是通过if-else或者switch子句,通过订单内部的一个表示状态的属性,判断出当前订单是否可以寄送和取消。
可是这样严重影响了程序代码的课扩展性,想想一下,如果我需要添加一种叫做“已出库”的状态,此时订单表现为可以被取消但是不可以再次申请寄送,那我们就需要在if-else子句中添加新的逻辑;又或者我们需要改变业务规则寄送的订单可以在没有完成前取消,那么我们又需要对订单的实现代码做逻辑更改,很明显,这样对扩展性来说是一个大问题。
所以,我们的解决方案是将订单的行为推送到订单状态自身,这样即使扩展再多的订单状态或者对状态行为进行更改,也可以轻松应对,只对很少的类进行更改,并且不会牵涉到太多代码逻辑。
解决问题走起
首先创建一个订表示订单状态的枚举OrderStatus
namespace Pattern.State
{
public enum OrderStatus
{
New=0,
Shipped=1,
Canceled=2
}
}
然后创建一个借口IOrderState,定义订单的行为和保存订单的状态枚举值
namespace Pattern.State
{
public interface IOrderState
{
bool CanShip(Order order);
void Ship(Order order);
bool CanCancel(Order order);
void Cancel(Order order);
OrderStatus Status { get; }
}
}
接下来就是最重要的Order类
namespace Pattern.State
{
public class Order
{
private IOrderState orderState;
public Order(IOrderState orderState)
{
this.orderState = orderState;
}
public int Id { get; set; }
public string CustomerName { get; set; }
public string Address { get; set; }
public OrderStatus Status()
{
return orderState.Status;
}
public bool CanCancel()
{
return orderState.CanCancel(this);
}
public void Cancel()
{
if (CanCancel())
{
orderState.Cancel(this);
}
}
public bool CanShip()
{
return orderState.CanShip(this);
}
public void Ship()
{
if (CanShip())
{
orderState.Ship(this);
}
}
internal void Change(IOrderState orderState)
{
this.orderState = orderState;
}
}
}
你可以看到,本来想象中的复杂了代码逻辑没有了,代码变得更易懂易扩展,因为我们将这些行为转到了IOrderState的子类中,单个子类只维护当前状态下订单的行为:
1.NewState
namespace Pattern.State
{
public class NewState:IOrderState
{
public bool CanShip(Order order)
{
//some logic here
return true;
}
public void Ship(Order order)
{
order.Change(new ShippedState());
}
public bool CanCancel(Order order)
{
return true;
}
public void Cancel(Order order)
{
order.Change(new CanceledState());
}
public OrderStatus Status
{
get { return OrderStatus.New; }
}
}
}
2.ShippedState
namespace Pattern.State
{
public class ShippedState:IOrderState
{
public bool CanShip(Order order)
{
return false;
}
public void Ship(Order order)
{
throw new InvalidOperationException();
}
public bool CanCancel(Order order)
{
return false;
}
public void Cancel(Order order)
{
throw new InvalidOperationException();
}
public OrderStatus Status
{
get { return OrderStatus.Shipped }
}
}
}
3.CanceledState
namespace Pattern.State
{
public class CanceledState:IOrderState
{
public bool CanShip(Order order)
{
return false;
}
public void Ship(Order order)
{
throw new InvalidOperationException();
}
public bool CanCancel(Order order)
{
return false;
}
public void Cancel(Order order)
{
throw new InvalidOperationException();
}
public OrderStatus Status
{
get { return OrderStatus.Canceled; }
}
}
}
最后我们创建一个OrderFactory
namespace Pattern.State
{
public static class OrderFactory
{
public static Order CreateOrder(string customerName, string address)
{
IOrderState orderState = new NewState();
Order order = new Order(orderState);
return order;
}
}
}
最后,通过一个控制台应用程序来测试一下:
namespace Pattern.Console
{
class Program
{
static void Main(string[] args)
{
Order order = OrderFactory.CreateOrder("小白哥哥", "天津市和平区");
if (order.CanShip())
{
System.Console.WriteLine("订单当前可以寄送");
}
order.Ship();
if (!order.CanShip())
{
System.Console.WriteLine("订单当前不可以寄送");
}
System.Console.ReadKey();
}
}
}
State模式的经典应用场景:订单处理(c#实现)的更多相关文章
- ASP.NET运行时详解 集成模式和经典模式
遗留问题 在<ASP.NET运行时详解 生命周期入口分析>中遗留两个问题,包括Application的InitInternal方法执行细节.IIS6和II7经典模式请求管道管理类Appli ...
- 敏捷软件开发(1)--- STATE 模式
如果状态在运行过程中,不停的切换和改变,我们怎么办? 状态的迁移是我们生活和工程中非常普遍的一个概念.于是在数学上有一种理论来分析和解决这个问题. 有限状态机理论是一个非常成熟的理论,所有动作和流程的 ...
- state模式理解
state模式应用场景 条件判断很多的情况 比如有很多if else语句:switch case语句等等. 如果以后业务越来越复杂,条件判断有100多个,每种条件的处理逻辑很复杂,不止一个业务逻辑会重 ...
- Java设计模式之《桥接模式》及应用场景
摘要: 原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6497919.html 这里摘抄一份他处的概念,你可以不必理会,先看下面得讲解与实例, ...
- Java设计模式(19)状态模式(State模式)
State的定义:不同的状态,不同的行为:或者说,每个状态有着相应的行为. 何时使用状态模式 State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If else ...
- 45个 GIT 经典操作场景,专治不会合代码
大家好,我是小富~ 技术交流关注公众号:程序员内点事 传送门:原文地址 git对于大家应该都不太陌生,熟练使用git已经成为程序员的一项基本技能,尽管在工作中有诸如 Sourcetree这样牛X的客户 ...
- 无聊之作,RPGdemo制作(一)角色state模式
今天周末,在家无事可做,不知道为什么,突发奇想,想写一个RPG游戏的demo玩玩.所以就记录一下. 第一步要做的是,为以后的角色类写一个state模式的类,考虑到可能以后会用到,所以用模版来实现, / ...
- State模式
地铁十字转门 状态迁移表格. 起始状态 触发迁移的事件 终止状态 要执行的动作. Locked Coin UnLocked UnLock UnLocked Pass ...
- Behavioral模式State模式
1.意向 同意一个目标,然后改变其内部状态,改变它的行为. 对象似乎改变它的类别. 2.别名 状态对象(Objects for States) 3.动机 考虑一个表示网络连接的类TCPConnecti ...
随机推荐
- SQL语句最基本的性能优化方法
有些人还不知道sql语句的基本性能优化方法,在此我简单提醒一下,最基本的优化方法: 1.检查是否缺少索引.调试的时候开启“包括实际的执行计划” 执行后会显示缺少的索引, 然后让dba帮助添 ...
- C#形参,实参,值传递参数,引用传递参数,输出参数,参数数组的学习
1)形参 形参顾名思义就是形式上的参数,不是实际的参数,它代替实际传入方法的值.在方法体代码中代表了值本身参与运算.形参定义于参数中,它不同于方法体内局部变量,因为是一个变量,在它的作用域内不允许存在 ...
- Maven测试
生命周期阶段需要绑定到某个插件的目标才能完成真正的工作,test阶段正是与maven-surefire-plugin的test目标相绑定了,这是一个 内置的绑定. 在默认情况下,maven-suref ...
- maven使用入门(pom)
mvn clean complie mvn clean test mvn clean package mvn clean install(该任务将该项目输出的jar安装到了Maven本地仓库中) 各个 ...
- python 将页面保存为word
将博客或者留言页面保存为word文档 -----------2016-5-11 14:40:04-- source:http://blog.csdn.net/how8586/article/detai ...
- asp.net实现大文件上传
需要下载NeatUpload插件 上传页面: <%@ Page Language="C#" AutoEventWireup="true" CodeFile ...
- Excel 、数据库 一言不合就转换 (zhuan)
http://blog.csdn.net/marksinoberg/article/details/52280786 ***************************************** ...
- 全局变量报错:UnboundLocalError: local variable 'l' referenced before assignment
总结: 内部函数,不修改全局变量可以访问全局变量 内部函数,修改同名全局变量,则python会认为它是一个局部变量 在内部函数修改同名全局变量之前调用变量名称(如print sum),则引发Unbou ...
- C#_List转换成DataTable
/// <summary> /// 讲list集合转换成datatable /// </summary> /// <param name="list" ...
- libsvm 之 easy.py(流程化脚本)注释
鉴于该脚本的重要性,很有必要对该脚本做一个全面的注释,以便可以灵活的使用libsvm. #!/usr/bin/env python # 这种设置python路径的方法更为科学 import sys i ...