当前位置:首页 > 网络编程 > WEB编程 > ASP.net >  职责链模式在开发中的应用

 职责链模式在开发中的应用

点击次数:20 次 发布日期:2008-11-26 22:26:26 作者:源代码网
源代码网推荐     
源代码网推荐  我在《软件设计精要与模式》第19章中介绍了职责链模式在实际项目中的应用,由于引入了该模式,使得对象在职责划分上有了更清晰的结构,然而由于项目场景的诸多限制,总有几分“为模式而模式”的生涩感觉。最近在开发WCF的相关项目时,又一次应用了职责链模式,一方面加深了自己对设计模式的进一步理解,也积累了一些心得,可以与各位分享。
源代码网推荐  
源代码网推荐  在该项目中,我希望实现对Endpoint的合法性检验,其中对于绑定而言,则包含了许多约束,例如绑定与URI样式的约束,例如绑定与服务契约设计的约束。绑定不同,则向对应的约束也不相同。为了更好地体现Endpoint,我在项目中定义了属于自己的Endpoint类:
源代码网推荐   public class ServiceEndpoint
源代码网推荐   {
源代码网推荐   public Uri Address
源代码网推荐   {
源代码网推荐   get;
源代码网推荐   set;
源代码网推荐   }
源代码网推荐  
源代码网推荐   public Binding Binding
源代码网推荐   {
源代码网推荐   get;
源代码网推荐   set;
源代码网推荐   }
源代码网推荐  
源代码网推荐   public Type ContractType
源代码网推荐   {
源代码网推荐   get;
源代码网推荐   set;
源代码网推荐   }
源代码网推荐   }
源代码网推荐  如果考虑最简单的实现方式,我们完全可以通过分支语句,判断不同的绑定类型,然后执行对绑定约束的检查,例如:
源代码网推荐  
源代码网推荐  public class BindingConstraint
源代码网推荐  
源代码网推荐  {
源代码网推荐  
源代码网推荐  public bool Constraint(ServiceEndpoint endpoint)
源代码网推荐  
源代码网推荐  {
源代码网推荐  
源代码网推荐  bool flag = false;
源代码网推荐  
源代码网推荐  switch (endpoint.Binding.Name)
源代码网推荐  
源代码网推荐  {
源代码网推荐  
源代码网推荐  case "BasicHttpBinding":
源代码网推荐  
源代码网推荐  //check the BasicHttpBinding;
源代码网推荐  
源代码网推荐  
源代码网推荐  
源代码网推荐  flag = true;
源代码网推荐  
源代码网推荐  break;
源代码网推荐  
源代码网推荐  case "NetTcpBinding":
源代码网推荐  
源代码网推荐  //check the NetTcpBinding;
源代码网推荐  
源代码网推荐  break;
源代码网推荐  
源代码网推荐  case "NetPeerTcpBinding":
源代码网推荐  
源代码网推荐  //check the NetPeerTcpBinding;
源代码网推荐  
源代码网推荐  break;
源代码网推荐  
源代码网推荐  //...Other bindings" constraint;
源代码网推荐  
源代码网推荐  }
源代码网推荐  
源代码网推荐  
源代码网推荐  
源代码网推荐  return flag;
源代码网推荐  
源代码网推荐  }
源代码网推荐  
源代码网推荐  }
源代码网推荐  
源代码网推荐  这是一个合适的设计,无可厚非。然而,我们所面临的关于绑定的约束性检查,远非几行代码就可以实现。例如,对于WSDualHttpBinding绑定而言,我们就需要判断传递进来的契约类型是否具有回调契约。当然,我们可以分别将这些约束性检查放入到专门的方法,甚至是专门的类中,但不可避免的是,我们会让Constraint方法的switch语句变得越来越长。
源代码网推荐  
源代码网推荐  这还不是关键的,最主要的是我们需要检查的绑定存在扩展的可能,因为除了WCF自身提供的绑定类型之外,我们还可以提供CustomBinding或其它自定义绑定,一旦可能增加绑定,就需要修改这里的Constraint()方法。这样的设计就难免捉襟见肘了。事实上,在.NET Framework 3.5中,微软就为WCF新增加了几个绑定,例如WebHttpBinding。
源代码网推荐  
源代码网推荐  此时,我们就可以考虑采用职责链模式,由于我们是针对绑定类型进行约束性检查,我们可以为每个绑定类型定义一个约束对象,然后对其进行抽象,设计类图如下所示:
源代码网推荐  
源代码网推荐  首先,我们需要定义一个基类BindingConstraint,如下所示:
源代码网推荐   public abstract class BindingConstraint//:IEndpointConstraint
源代码网推荐   {
源代码网推荐   protected fields#region protected fields
源代码网推荐  
源代码网推荐   protected BindingConstraint m_bindingConstraint;
源代码网推荐   protected bool m_hasNextConstraint = false;
源代码网推荐  
源代码网推荐   #endregion
源代码网推荐  
源代码网推荐   public methods#region public methods
源代码网推荐  
源代码网推荐   public void AddConstraint(BindingConstraint constraint)
源代码网推荐   {
源代码网推荐   m_bindingConstraint = constraint;
源代码网推荐   m_hasNextConstraint = true;
源代码网推荐   }
源代码网推荐  
源代码网推荐   #endregion
源代码网推荐  
源代码网推荐   public abstract methods#region public abstract methods
源代码网推荐  
源代码网推荐   public abstract bool Constraint(ServiceEndpoint endpoint);
源代码网推荐  
源代码网推荐   #endregion
源代码网推荐  
源代码网推荐   }
源代码网推荐  这是一个抽象类,包含了两个protected字段,其中m_bindingConstraint即形成职责链的关键,通过AddConstraint()方法可以将BindingConstraint对象加入到职责链中,而字段m_hasNextConstraint则用来标识当前对象之下是否还存在BindingConstraint对象。抽象方法Constraint()则实现约束性检查的业务逻辑,同时还包括对职责链是否存在下一个职责对象的判断。例如BasicHttpBindingConstraint的定义如下:
源代码网推荐   public class BasicHttpBindingConstraint:BindingConstraint
源代码网推荐   {
源代码网推荐   public override bool Constraint(ServiceEndpoint endpoint)
源代码网推荐   {
源代码网推荐   if (endpoint.Binding.Name == "BasicHttpBinding")
源代码网推荐   {
源代码网推荐   //check BasicHttpBinding Constraint;
源代码网推荐   BasicHttpBinding binding = endpoint.Binding as BasicHttpBinding;
源代码网推荐   //...
源代码网推荐  
源代码网推荐   //check binding and address"s scheme if (endpoint.Address.Scheme.ToLower() != "http" && endpoint.Address.Scheme.ToLower() != "https")
源代码网推荐   {
源代码网推荐   throw new BindingConstraintException("the binding is mismatch with address schema.");
源代码网推荐   }
源代码网推荐  
源代码网推荐   return true;
源代码网推荐   }
源代码网推荐   else
源代码网推荐   {
源代码网推荐   if (m_hasNextConstraint)
源代码网推荐   {
源代码网推荐   return m_bindingConstraint.Constraint(endpoint);
源代码网推荐   }
源代码网推荐   else
源代码网推荐   {
源代码网推荐   return false;
源代码网推荐   }
源代码网推荐   }
源代码网推荐   }
源代码网推荐   }
源代码网推荐  根据传入的endpoint对象,判断绑定的名称是否为"BasicHttpBinding",如果是,则执行该约束对象的约束性检查,如果不是,则去寻找职责链中的其它对象(根据m_hasNextConstraint判断)。正是通过这样的实现方式,当客户端调用BindingConstraint的Constraint()方法时,就可以根据传入的ServiceEndpoint对象,智能地找到符合自己条件的BindingConstraint对象,并执行Constraint()方法进行约束性检查。
源代码网推荐  
源代码网推荐  在我的《软件设计精要与模式》一书中,在应用职责链模式时,我的建议是最好提供专门创建职责链的工厂类,在本例中自然也不例外:
源代码网推荐   public class BindingConstraintFactory
源代码网推荐   {
源代码网推荐   public static BindingConstraint CreateConstraint()
源代码网推荐   {
源代码网推荐   BindingConstraint basicHttp = new BasicHttpBindingConstraint();
源代码网推荐   BindingConstraint netTcp = new NetTcpBindingConstraint();
源代码网推荐   BindingConstraint netPeerTcp = new NetPeerTcpBindingConstraint();
源代码网推荐   BindingConstraint netNamedPipe = new NetNamedPipeBindingConstraint();
源代码网推荐   BindingConstraint wsHttp = new WSHttpBindingConstraint();
源代码网推荐   BindingConstraint wsFederationHttp = new WSFederationHttpBindingConstraint();
源代码网推荐   BindingConstraint wsDualHttp = new WSDualHttpBindingConstraint();
源代码网推荐   BindingConstraint netMsmq = new NetMsmqBindingConstraint();
源代码网推荐   BindingConstraint msmqIntegration = new MsmqIntegrationBindingConstraint();
源代码网推荐  
源代码网推荐   netMsmq.AddConstraint(msmqIntegration);
源代码网推荐   wsDualHttp.AddConstraint(netMsmq);
源代码网推荐   wsFederationHttp.AddConstraint(wsDualHttp);
源代码网推荐   wsHttp.AddConstraint(wsFederationHttp);
源代码网推荐   netNamedPipe.AddConstraint(wsHttp);
源代码网推荐   netPeerTcp.AddConstraint(netNamedPipe);
源代码网推荐   netTcp.AddConstraint(netPeerTcp);
源代码网推荐   basicHttp.AddConstraint(netTcp);
源代码网推荐  
源代码网推荐   return basicHttp;
源代码网推荐   }
源代码网推荐   }
源代码网推荐  通过CreateConstraint()方法,就可以像穿珠子一般,形成一条隐藏的职责链(在创建这样的职责链时,需要注意职责对象的先后次序),然后在客户端代码中,可以非常优雅的实现对绑定的约束性检查:
源代码网推荐  
源代码网推荐  private static BindingConstraint m_bindingConstraint = BindingConstraintFactory.CreateConstraint();
源代码网推荐  
源代码网推荐  
源代码网推荐  
源代码网推荐  public void AddServiceEndpoint(ServiceEndpoint endpoint)
源代码网推荐  
源代码网推荐  {
源代码网推荐  
源代码网推荐  if (m_bindingConstraint.Constraint(endpoint))
源代码网推荐  
源代码网推荐  {
源代码网推荐  
源代码网推荐  m_endpointsList.Add(endpoint);
源代码网推荐  
源代码网推荐  }
源代码网推荐  
源代码网推荐  }
源代码网推荐  
源代码网推荐  
源代码网推荐  不管传入的endpoint是何种类型的绑定,只要在职责链中创建了相对应的绑定约束对象,都可以进行约束性检查,且逻辑清楚,职责明确。如果对绑定进行了扩展,我们只需要新增对应的绑定约束对象,然后修改BindingConstraintFactory工厂类的工厂方法即可。
源代码网推荐  
源代码网推荐  使用职责链模式必须恰到好处,否则会成为模式滥用的反面教材。根据我对职责链模式的理解,可以认定只要同时符合下列三个条件,就可以引入职责链模式:
源代码网推荐  1、当一个方法的传入参数将成为分支语句的判断条件时;
源代码网推荐  2、当每一个分支的职责相对独立,且逻辑较为复杂时;
源代码网推荐  3、当分支条件存在扩展的可能时。
源代码网推荐  
源代码网推荐  至于职责链模式的最佳实践,则包含以下内容:
源代码网推荐  1、应尽量将职责链模式的抽象定义为抽象类,而不要定义为接口。这样有利于一些公共逻辑的重用。
源代码网推荐  2、应在实现职责链模式的同时,提供创建职责链的工厂类。
源代码网推荐  
源代码网推荐    做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。
源代码网推荐


源代码网供稿.
网友评论 (0)
会员中心
网络编程
本站推荐
网络编程之精华