好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

订单的几种实现方式(用不同的模式实现:装饰器模式、代理模式、命令模式、状态模式、模版模式)

订单的几种实现方式(用不同的模式实现:装饰器模式、代理模式、命令模式、状态模式、模版模式)

谈谈下订单的几种实现方式(用不同的模式实现:装饰器模式、代理模式、命令模式、状态模式、模版模式)

本文讲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 .component =  component;
        }
          public   bool   NewOrder(OrderInfo order)
        {
              if  (Identity.UserID <=  0  )
                  throw   new  Exception( "  Authorization exception  "  );
              return   this  .component.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 .component =  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  .component.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://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于订单的几种实现方式(用不同的模式实现:装饰器模式、代理模式、命令模式、状态模式、模版模式)的详细内容...

  阅读:55次