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 ...
随机推荐
- 键盘unicode值对照表
A:65 B:66 C:67 D:68 E:69 F:70 G:71 H:72 I:73 J:74 K:75 L:76 M:77 N:78 O:79 P:80 Q:81 R:82 S:83 T:84 ...
- CUBRID学习笔记 39 net使用dataset 返回查询的数据
using CUBRID.Data.CUBRIDClient; namespace DataSetExample { class Program { static ...
- 【BZOJ】4636: 蒟蒻的数列
4636: 蒟蒻的数列 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 145 Solved: 71[Submit][Status][Discuss] ...
- 搭建SSH入过的那些坑
1.添加完相关jar包,写完配置文件,写完测试类,运行提示 WARN:Establishing SSL connection without server's identity verificatio ...
- iOS - Notification 通知
1.Notification 通知中心实际上是在程序内部提供了消息广播的一种机制,它允许我们在低程度耦合的情况下,满足控制器与一个任意的对象进行通信的目的.每一个 iOS 程序(即每一个进程)都有一个 ...
- CDN学习笔记二(技术详解)
一本好的入门书是带你进入陌生领域的明灯,<CDN技术详解>绝对是带你进入CDN行业的那盏最亮的明灯.因此,虽然只是纯粹的重点抄录,我也要把<CDN技术详解>的精华放上网.公诸同 ...
- c++ vector 简单实现。
第二次修改: 1)熟悉基本的模板编程,头文件和定义必须放到一起. 2)熟悉内存管理模板类 allocator<T>. 1.使用标准库的内存管理类 allocator<T> 代替 ...
- iOS开发之如何修改Mac截屏保存路径
如何修改Mac截屏保存路径 MAC OS X系统默认的截图路径是桌面文件夹,默认的截图格式是 PNG 图片格式,如何自定义设置呢? 截图保存路径 打开终端(Terminal)并输入如下命令: de ...
- iOS 开发之照片框架详解(3)
http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 三. 常用方法的封装 虽然 Phot ...
- openfire控制台登录不了的解决
不知道为什么,openfire服务器后台,发生几次密码都登录不上去的问题,密码肯定没错,第一次就是默认的用户名:admin,密码:admin,然,第三天,说我密码错误,后来重装软件才弄好, 然后又发生 ...