走向.NET架构设计—第五章—业务层模式,原则,实践(后篇)

简介:
走向.NET 架构设计 第五章 业务层模式,原则,实践(后篇)
  前言:在上一篇文章中,讲述了一些设计模式的使用,本篇首先接着介绍还没有讲完的一些设计模式,然后再讲述一些架构模式中的超类模式,作为本篇的结尾。
 
本篇的议题如下:
架构模式         
设计模式         
设计原则
 
 
  设计模式
  本篇文章主要是接着讨论的在业务层可以采用的或者常用的一些设计模式:
  Factory Method
  Decorator
  State
  Strategy
 
  State 模式
  状态模式允许一个对象在随着它的状态变化而改变它自身的一些行为。
    在项目开发的过程中,有一些类,例如一个业务类常常是有自己的一些状态的,而且还存在状态之间的一些转换,有些状态之间是可以进行转换的,有些状态之间是不能转换的。就拿一个汽车来举例子,汽车有很多的状态:静止,启动,前进,后退,停车。而且不能由 前进 状态转为“启动”状态。
 
      很多朋友知道 state 模式的用法和结构,朋友们应该也清楚在状态之间的转换用 swtich.. case 的一些弊端。在项目中,很多时候就没有 一定 ”,” 非得 要用 state 模式来解决类似的问题,即使可以用 state 模式来解决。如果变化不大, switch.. case 就够用了。
 
      下面还是来首先来看看使用 state 模式的一些例子。
 
      还是采用电子商务为背景来举例:每一个订单都是有状态的: New (新的) ,Shipped (已经发货), Canceled( 已取消 ) 。我们知道一个新的订单可以被变为 取消 的状态,也可以成为 已发货 状态。但是订单不能从 已发货 状态,变为 取消 的状态。
 下面就是例子中的类图:
  
 
  首先还是创建一个名为 :ASPPatterns.Chap5.StatePattern 的解决方案,添加一个名为 :ASPPattern.Chap5.StatePattern.Model 的类库:
   
 
  然后添加在 Model 的类库中添加一个表示状态接口的定义: IOrderState:
  
ExpandedBlockStart.gif 代码
  public   interface  IOrderState
    {        
        
bool  CanShip(Order Order);
        
void  Ship(Order Order);

        
bool  CanCancel(Order Order);
        
void  Cancel(Order order);

        OrderStatus Status { 
get ; }
    }
 
 
  下面来定义个表示订单状态的枚举:
 
public   enum  OrderStatus
    {
       New 
=   0 ,
       Shipped 
=   1 ,
       Canceled 
=   2
    }
 
 
然后我们来看看,真正要进行状态转化的那个订单类:
 
代码
  public   class  Order
    {
        
private  IOrderState _orderState;       

        
public  Order(IOrderState baseState)
        {
            _orderState 
=  baseState; 
        }

        
public   int  Id {  get set ; }

        
public   string  Customer {  get set ; }

        
public  DateTime OrderedDate {  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)
        {
            _orderState 
=  OrderState;
        }
    }
 
 
      其实状态模式一个最主要的思想就是:把状态之间的转换分离出来,把每一个状态分解为一个个的状态的类,然后这些状态来负责如何在不同的状态之间的转换。也就是说,就本例而言,以前我们会在 Order 类中写上如下的语句:
 
ExpandedBlockStart.gif 代码
 
public   void  ChangeStatus()
        {
            
switch  (Status)
            {
                
case  OrderStatus.New:
                    
// .... do some things
                    
break ;
                
case  OrderStatus.Shipped:
                    
// .... do some things
                    
break ;

                
case  OrderStatus.Canceled:
                    
// .... do some things
                    
break ;
            }
        }

 
 
      我们知道其实此时就是由 Order 类来控制了状态之间的转换。其实 state 模式的就是让那些“状态”变为一个“有思想”的状态类,这些类自己来负责如何以及何时转换到其他的状态,这样 Order 的“负担”就减轻了。还有一个就是大家常常会 批判 :如何要添加一个新的状态,那么 ChangeStatus 方法势必会变化,因为这个方法控制了状态之间的转换,如果把状态的转换逻辑分离出去,最好做到添加或者减少状态都不会影响现有的 Order 就更好了。
 
下面的讲述有点直接,希望不熟悉 state 模式的朋友先“撑下去” J
1.        当创建一个订单的时。候,这个订单的状态肯定就是 ”New”( 新的 ) 。那么我们可能就传入一个表示“ New ”状态的类: OrderNewStatus:
new  Order(OrderNewState newStatus)
OrderNewStatus 把订单的状态标记为 New
      我们知道:订单的状态为 New 的时候,状态可以向 Canceled Shipped 转换,那么 OrderNewStatus 的定义可能如下:
 
代码
  public   class  OrderNewState : IOrderState
    {
        
public   bool  CanShip(Order Order)
        {
            
return   true ;
        }

        
public   void  Ship(Order Order)
        {
            Order.Change(
new  OrderShippedState());
        }

        
public  OrderStatus Status
        {
            
get  {  return  OrderStatus.New; }
        }

        
public   bool  CanCancel(Order Order)
        {
            
return   true ;
        }

        
public   void  Cancel(Order order)
        {
            order.Change(
new  OrderCanceledState());
        }

        
public   new  Order(OrderNewState newStatus);

    }
 
 
2.        当新创建的订单处理到一定的流程的时候,例如要发货了,此时要更新订单的状态,此时我们只要调用 Order ship 方法就行了。其实此时我们就是在调用 NewOrderStatus 类的 Ship 方法,这个类的 ship 方法知道怎么做:先判断 Order 的是否可以向 Shipped 状态转换 ( 调用 CanShip 方法 ) ,如果可以,那么就 new 一个 OrderShippedStatus 状态的类,然后用这个类去替换原来的 NewOrderStatus( 调用 Order 类的 Change 方法 ) ,这样, Order 的状态就是 Shipped 了,但是 Order 完全不用管状态之间是如何变化的。
 
代码
     public   class  OrderShippedState : IOrderState 
    {        
        
public   bool  CanShip(Order order)
        {
            
return   false ;
        }

        
public   void  Ship(Order order)
        {            
            
throw   new  NotImplementedException( " You can't ship a shipped order! " );
        }
        
        
public  OrderStatus Status
        {
            
get  {  return  OrderStatus.Shipped; }
        }
        
        
public   bool  CanCancel(Order Order)
        {
            
return   false ;
        }

        
public   void  Cancel(Order order)
        {
            
throw   new  NotImplementedException( " You can't ship a shipped order! " );
        }

    }
 
 
3.         Canceled 状态也同理,我这里就不在赘述了。
 
代码
public   class  OrderCanceledState : IOrderState 
    {        
        
public   bool  CanShip(Order Order)
        {
            
return   false ;
        }

        
public   void  Ship(Order Order)
        {
            
throw   new  NotImplementedException( " You can't ship a cancelled order! " );
        }

        
public  OrderStatus Status
        {
            
get  {  return  OrderStatus.Canceled; }
        }        

        
public   bool  CanCancel(Order Order)
        {
            
return   false ;
        }

        
public   void  Cancel(Order order)
        {
            
throw   new  NotImplementedException( " You can't ship a cancelled order! " );
        }
    }
 
 
我们用一个 UML 图来结束 state 模式的讲述:
 
 
Strategy模式
其实策略模式,我这里不打算作太多的讲述,其实这种模式大家到处可见,我们常常在 ASP.NET 中常常提起的 Provider 模式,其实就是策略模式的一种实现。
大家看看结构图,基本上就明白了:
 
在上述的图中 Context 依赖一个 IStrategy 接口,我们可以决定让 Context 使用 IStrategy 的任意的一个实现者: ConcreteStrategyA  或者 ConcreteStrategyB 。其实就是可以替换不同的实现者。可能大家在数据访问层那块有的体验更加的明显:定义一个 IDataProvider ,然后实现一个 AdoDotNetProvider 和一个 LinqToSqlProvider
 
架构模式
下面就来补充一些架构模式的知识,下文主要讲述: Layer Supertype 模式(超类模式)
 
超类模式就是定义一个基类,然后其他的所有的类都从这个类中继承。对于业务层而言,在超类中可能会定义一些通用的业务规则和验证方法,这样就这些代码被到处分散。也体现了继承的一个好处。
 
下面我们就来看一个项目中的例子(电子商务为例), 类结构如下:
 
大家可以看到,所有的业务类都是从 EntityBase 继承的。
 
代码
   public   abstract   class  EntityBase < T >
    {        
        
private  T _Id;
        
private   bool  _idHasBeenSet  =   false ;
        
private  IList < string >  _brokenRules  =   new  List < string > ();

        
public  EntityBase()
        { }

        
public  EntityBase(T Id)
        {
            
this .Id  =  Id;
        }

        
public  T Id
        {
            
get  {  return  _Id; }
            
set
            {
                
if  (_idHasBeenSet)
                    ThrowExceptionIfOverwritingAnId();

                _Id 
=  value;
                _idHasBeenSet 
=   true ;
            }
        }

        
private   void  ThrowExceptionIfOverwritingAnId()
        {
            
throw   new  ApplicationException( " You cannot change the id of an entity. " );
        }

        
public   bool  IsValid()
        {
            ClearCollectionOfBrokenRules();
            CheckForBrokenRules();
            
return  _brokenRules.Count()  ==   0 ;
        }

        
protected   abstract   void  CheckForBrokenRules();        

        
private   void  ClearCollectionOfBrokenRules()
        {
            _brokenRules.Clear(); 
        }

        
public  IEnumerable < string >  GetBrokenBusinessRules()
        {
            
return  _brokenRules;
        }

        
protected   void  AddBrokenRule( string  brokenRule)
        {
            _brokenRules.Add(brokenRule);
        }
    }
 
在这个超类中,提供了保存每个业务类唯一标识的逻辑,并且确保这个标识一旦设定就不会被改变。而且这个超类还提供一些简单的验证逻辑。
 
我们再来看看如何使用这个超类,下面定义了一个 Customer 的业务类:
 
代码
   public   class  Customer : EntityBase < long >
    {
        
public  Customer() { }

        
public  Customer( long  Id)
            : 
base (Id)
        { }

        
public   string  FirstName {  get set ; }
        
public   string  LastName {  get set ; }

        
protected   override   void  CheckForBrokenRules()
        {
            
if  (String.IsNullOrEmpty(FirstName))
                
base .AddBrokenRule( " You must supply a first name. " );

            
if  (String.IsNullOrEmpty(LastName))
                
base .AddBrokenRule( " You must supply a last name. " );
        }
    }
 
在这个类中,我们定义了唯一标识的类型 :long ,而且还定义了一些业务规则: FirstName, LastName 不为空。至于如何调用这些验证规则,在超类中已经实现了,此时业务类就“轻松”了很多 起码不用再次写那些相类似的代码了,实现了一定程度上的代码重用。
 
今天就讲到这里了,不正确之处,还望朋友们指出,见谅!
多谢支持!




















本文转自yanyangtian51CTO博客,原文链接: http://blog.51cto.com/yanyangtian/434979 ,如需转载请自行联系原作者


相关文章
|
1月前
|
SQL 开发框架 数据可视化
企业应用开发中.NET EF常用哪种模式?
企业应用开发中.NET EF常用哪种模式?
|
3月前
|
小程序 Java 数据管理
Java前后端分离架构开发的智慧校园电子班牌系统源码(SaaS模式)
.智慧校园设备管理: 设备管理主要对班级中正在使用的电子智慧班牌进行管理,基本功能包含(开关机状态、班级信息、设备型号、开关机信息、电子智慧班牌截屏信息、教师编号、设备ID、在线和离线状态、电子智慧班牌更新时间等)
39 0
|
3月前
|
设计模式 Linux 程序员
Linux驱动的软件架构(一):驱动的软件设计模式理念
Linux驱动的软件架构(一):驱动的软件设计模式理念
36 0
|
3月前
|
存储 缓存 负载均衡
架构的模式
架构的模式
|
8天前
|
前端开发 安全 JavaScript
计算机软件从 CS 模式到 BS 架构迁移背后的动因
计算机软件从 CS 模式到 BS 架构迁移背后的动因
20 0
|
17天前
|
存储 监控 安全
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
金石推荐 | 【分布式技术专题】「单点登录技术架构」一文带领你好好认识以下Saml协议的运作机制和流程模式
16 0
|
25天前
|
运维 安全 Linux
LAMP架构调优(八)——Apache Worker模式调优
LAMP架构调优(八)——Apache Worker模式调优
9 0
|
26天前
|
缓存 运维 Linux
LAMP架构调优(七)——Apache Prefork模式调优
LAMP架构调优(七)——Apache Prefork模式调优
15 2
|
26天前
|
数据安全/隐私保护 Windows
.net三层架构开发步骤
.net三层架构开发步骤
7 0
|
1月前
|
消息中间件 存储 缓存
性能基础之大型网站技术架构模式
【2月更文挑战第15天】性能基础之大型网站技术架构模式
67 3
性能基础之大型网站技术架构模式