订单的几种实现方式(用不同的模式实现:装饰器模式、代理模式、命令模式、状态模式、模版模式)
谈谈下订单的几种实现方式(用不同的模式实现:装饰器模式、代理模式、命令模式、状态模式、模版模式)
本文讲PlaceOrder函数的实现(重点在业务逻辑层),让我们来分别用不同的设计模式来实现吧:装饰器模式、代理模式、命令模式、状态模式、模版模式。
假设我们实现需求如下:
在PlaceOrder函数中需要做如下工作
1. 检查权限,未登录的不能递交订单
2. 计算税
3. 记录日志
好了,让我们分别来实现吧....当然,是用不同的设计模式分别实现。
装饰器模式实现
请看PlaceOrder函数方法体:
public bool PlaceOrder(OrderInfo order)
{
try
{
OrderService srv = new OrderService(); //核心业务类
TaxDecorator4OrderService tax = new TaxDecorator4OrderService(srv); //第一次装饰
LogDecorator4OrderService log = new LogDecorator4OrderService(tax); //第二次装饰
PermissionDecorator4OrderService permission = new PermissionDecorator4OrderService(log); //第三次装饰
return permission.NewOrder(order); //这里调用的是最后一个装饰器的方法(会链式反应,调用全部的关联函数)
}
catch (Exception ex) //由于PermissionDecorator4OrderService中会抛出exception,因此用了try, catch
{
Console.WriteLine( " exception: " + ex.Message);
return false ;
}
}
实现方法
1. 写一个公共的接口,让“核心业务类”、“装饰类”都实现这个接口
2. “装饰类”的构造器需要能注入这个公共接口
3. 然后像上面那样拼装饰链条
装饰器代码如下(核心代码):
public class PermissionDecorator4OrderService: IOrderServiceComponent //上面所说的公共接口
{
IOrderServiceComponent component;
public PermissionDecorator4OrderService( IOrderServiceComponent component ) //要提供注入的地方,此处是构造函数注入方式,你也可以根据情况使用其他注入方式
{
this 测试数据ponent = component;
}
public bool NewOrder(OrderInfo order)
{
if (Identity.UserID <= 0 )
throw new Exception( " Authorization exception " );
return this 测试数据ponent.NewOrder(order);
}
}
代码在本页最下方有下载。
代理模式实现
请看PlaceOrder函数方法体:
public bool PlaceOrder(OrderInfo order)
{
try
{
OrderService srv = new OrderService(); //核心业务类(这个类就是要被控制访问的类)
OrderServiceAgency srvAgency = new OrderServiceAgency(); //代理类,外界的调用是通过它的,由它来转发核心业务类的调用,意图在于控制访问
srvAgency.SetServiceComponent(srv); //此处为注入(方法注入方式),当然,你也可以使用构造器注入
return srvAgency.NewOrder(order); //看,此处调用的是代理的NewOrder
}
catch (Exception ex)
{
Console.WriteLine( " exception: " + ex.Message);
return false ;
}
}
“核心业务类”、“代理类”,这2个类的外观是相同的,最简单的方式实现这个模式是
1. 为这2种类定义一个接口,这2种类都去实现
2. “代理类”除了要实现这个接口之外,还要持有这个接口的一个instance(这样才能转发调用)
3. “代理类”需要提供注入方式:构造函数、方法、属性注入方式
“代理类”代码如下(核心):
public class OrderServiceAgency : IOrderServiceComponent //实现同一个接口(外观一致)
{
private IOrderServiceComponent component; //要持有一个instance
public void SetServiceComponent(IOrderServiceComponent component) //注入这个instance
{
this 测试数据ponent = component;
}
public bool NewOrder(OrderInfo order) //“代理类”的接口方法中,可以自定义一些逻辑
{
if (Identity.UserID <= 0 )
throw new Exception( " Authorization exception " );
order.Total += order.Total * ( decimal ) 0.02 ; // 模拟税收
Console.WriteLine( " loging... " );
return this 测试数据ponent.NewOrder(order); //转发请求到“业务类”
}
}
代码在本页最下方有下载。
命令模式
请看PlaceOrder函数方法体:
public bool PlaceOrder(OrderInfo order)
{
try
{
NewOrderCommandResult result = new NewOrderCommandResult(); //由于命令模式不像直接call、返回结果方式,因此写了这个callback类,专门用来放执行结果
CheckPermissionCommand permissionCommand = new CheckPermissionCommand( new RealExecuters.PermissionService()); //检查权限命令
CalculateTaxCommand calculateTaxCommand = new CalculateTaxCommand( new RealExecuters.TaxCalculator(), order); //计算税命令
LogCommand logCommand = new LogCommand( new RealExecuters.LogService()); //记录日志命令
NewOrderCommand newOrderCommand = new NewOrderCommand( new RealExecuters.OrderService(), order, result); //调用"核心业务类"命令
List <IPlaceOrderCommand> list = new List<IPlaceOrderCommand> (); //把这些命令都打包到一个list中
list.Add(permissionCommand);
list.Add(calculateTaxCommand);
list.Add(logCommand);
list.Add(newOrderCommand);
list.ForEach(t => t.Execute()); //遍历执行
return result.IsSuccess; //callback的执行结果
}
catch (Exception ex)
{
Console.WriteLine( " exception: " + ex.Message);
return false ;
}
}
原本的调用方式是直接call,然后目标对象返回结果,命令模式是在这步骤中间截取了一道,它通过增加一个command类来中转对目标方法的调用,此时,只要保存这些command类就能打包命令的执行了。
核心代码如下:
interface IPlaceOrderCommand //命令的抽象接口
{
void Execute(); //就那么一个方法,Execute(), 而且是void和没有参数的
}
class LogCommand : IPlaceOrderCommand
{
private LogService logService;
public LogCommand(LogService logService) //不同的Command需要注入相应的真正实现这个命令的类
{
this .logService = logService;
}
public void Execute()
{
this .logService.Log( " loging... " ); //只是中转调用
}
}
class PermissionCheckCommand: IPlaceOrderCommand
class Log2Command:IPlaceOrderCommand
当这些XXXXXXXCommand被instance之后,就可以保存到Queue或者List,又或者序列化。。。。统一Execute(),而且此时执行的话,外观已经一致了,并且没有入参,很方便。
至于这个模式的callback result怎么写,大家就看看demo代码吧,这里不说了。
代码在本页最下方有下载。
状态模式
请看PlaceOrder函数方法体:
public bool PlaceOrder(OrderInfo order)
{
try
{
bool isValidaUser = Identity.UserID > 0 ;
IOrderServiceComponent component = null ;
if (isValidaUser) //根据条件状态,去获取不同的对象,执行不一样的业务逻辑
component = new AuthorizaedNewOrderService();
else
component = new UnAuthorizaedNewOrderService();
return component.NewOrder(order);
}
catch (Exception ex)
{
Console.WriteLine( " exception: " + ex.Message);
return false ;
}
}
主要的原理是:把代码中大块的if/else中的代码extract到其他class中,实现要点:
1. 有几个分支,就写几个类,然后把if/else中的代码重构过去
2. 这些新增的类,需要实现同一个接口
核心代码如下:
public interface IOrderServiceComponent
{
bool NewOrder(OrderInfo order);
}
class UnAuthorizaedNewOrderService : IOrderServiceComponent
{
public bool NewOrder(OrderInfo order)
{
throw new Exception( " Authorization exception " );
}
}
class AuthorizaedNewOrderService : IOrderServiceComponent
{
public bool NewOrder(OrderInfo order)
{
order.Total += order.Total * ( decimal ) 0.02 ; // 模拟税收
// validate entity
// insert database
Console.WriteLine( " inserting database " );
Console.WriteLine( " loging... " );
return true ;
}
}
代码在本页最下方有下载。
模版模式
请看PlaceOrder函数方法体:
public bool PlaceOrder(OrderInfo order)
{
try
{
BaseOrderService srv = new AaronOrderService(); //BaseOrderService是定义的模版抽象类,里面定义了NewOrder函数的主要步骤逻辑
return srv.NewOrder(order); //AaronOrderService只是重写/实现BaseOrderService的某些方法函数,达到部分自定义,全局固定的状态
}
catch (Exception ex)
{
Console.WriteLine( " exception: " + ex.Message);
return false ;
}
}
这个模式在平台设计上也很有用,因为能够做到全局固定、局部变化,简而言之:该不变的就不变、该变的就要变,也有称为热点的。
核心代码如下:
public abstract class BaseOrderService
{
public bool NewOrder(OrderInfo order) //这个就是骨架了,逻辑步骤是固定住的
{
PermissionCheck();
TaxCalculate(order);
bool success= CreateNewOrder(order);
Log();
return success;
}
private void Log()
{
Console.WriteLine( " loging... " );
}
protected abstract bool CreateNewOrder(OrderInfo order); //这个函数没有实现,是需要去实现的
protected virtual void TaxCalculate(OrderInfo order) //这个函数实现了,但是定义成了virtual, 允许子类override
{
order.Total += order.Total * ( decimal ) 0.02 ;
}
private void PermissionCheck()
{
if (Identity.UserID <= 0 )
throw new Exception( " Authorization exception " );
}
}
下载demo 代码
自省推动进步,视野决定未来。
心怀远大理想。
为了家庭幸福而努力。
分类: 设计模式
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于订单的几种实现方式(用不同的模式实现:装饰器模式、代理模式、命令模式、状态模式、模版模式)的详细内容...