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 ...
随机推荐
- Beaglebone Black– 智能家居控制系统 LAS - 网页服务器 Node.js 、Web Service、页面 和 TCP 请求转 UDP 发送
上一篇,纯粹玩 ESP8266,写入了 init.lua 能收发 UDP.这次拿 BBB 开刀,用 BBB host 一个 web server ,用于与用户交互,数据来自 ESP8266 的 UDP ...
- [SAP ABAP开发技术总结]消息处理Messages
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- Struts BaseAction工具类,封装Session,Request,Application,ModelDriven
package com.ssh.shop.action; import java.io.InputStream; import java.lang.reflect.ParameterizedType; ...
- 学习Berkeley DB- 入门
1 导言 首先,我们要了解Berkeley DB的一些基本特性,在IBM的开发网站上有篇文章对其有比较清晰的介绍: 这篇文章讲到了BDB的设计思想和核心数据结构.以及数据访问算法:并有常用函数使用范例 ...
- 没有Path的Binding
当Binding源本身就是数据且不需要Path来指明时,可以设置Path的值为".",或直接省略Path.XAML中这个"."可以省略不写,但在C#代码中是不能 ...
- kakfa的常用命令总结
Kafka的版本间差异较大,下面是0.8.2.1的操作方法 首先cd到kafaka的bin目录下; #step1启动zookeeper服务 nohup bin/zookeeper-server-s ...
- LINQ之路 2:C# 3.0的语言功能(上)
在上一篇的LINQ介绍中,我们已经看到了隐式类型变量var,扩展方法(extension method)和lambda表达式的身影.没错,他们正是LINQ技术的基石,是他们让LINQ的实现成为可能,并 ...
- Spring AOP执行方法
execution(* springinaction.springidol.Instrument.play(..)) * 代表返回为任意类型 springinaction.springidol.I ...
- 2014 Multi-University Training Contest 5
hdu4911 max(逆序数-k,0) #include <iostream> #include<stdio.h> #include<vector> #inclu ...
- OpenGL的glScalef缩放变换函数详解
glScalef是openGL中的模型缩放函数,就是把当前矩阵与一个表示延各个轴对物体进行拉伸.压缩.反射的矩阵相乘.这个物体的每个点的x,y,z坐标与对应的xyz参数相乘. 先看函数定义void g ...