【问题标题】:Which design patterns to use to implement this business logic?使用哪些设计模式来实现此业务逻辑?
【发布时间】:2009-10-23 18:38:01
【问题描述】:

我正在尝试确定用于业务密钥验证 Web 服务的最佳设计模式。基本逻辑流程编码如下。该程序将采用一个参数并使用一个字段来帮助确定在搜索可以找到此业务密钥的多个系统时采用的路径。首先搜索System1,如果没有找到,搜索System2和System3。 System1 搜索逻辑依赖于传递给原始验证方法的参数中的一个字段。

我不确定要使用哪种设计模式。看起来命令、责任链、模板方法都可以在这里使用。

通过下面的实现,我看到了以下问题:

  1. 每个 SearchSystemX 方法都需要知道如果没有找到业务键则返回 null,以便“控制”方法继续搜索其他系统。

  2. 每个 SearchSystemX 都必须知道如何填充业务对象,目前只是通过简单的原始字符串实现,但这只是示例。

请告诉我你的想法。

public string Validate (string parms) {
 string returnValue = null;

 returnValue = SearchSystem1(parms);

 if (returnValue == null) {
  returnValue = SearchSystem2(parms);

  if (returnValue != null) {
   returnValue = SearchSystem3(parms);
  }
  else if (returnValue == null) {
   if (parms == "Criteria1") {
    returnValue = SearchSystem4(parms);

    if (returnValue == null) {
     throw new ApplicationException("ID Invalid");
    }
   }
   else if (parms == "Criteria2") {
    throw new ApplicationException("ID Invalid");
   }
  }
 }
 return returnValue;

private string SearchSystem1 (string parms) {
 string returnValue = null;

 if (parms == "Criteria1") {
  returnValue = SearchSystem1UsingColumn1(parms);
 }
 else if (parms == "Criteria2") {
  returnValue = SearchSystem1UsingColumn2(parms);

  if (returnValue == null) {
   returnValue = SearchSystem1UsingColumn4(parms);
  }
 }

 if (returnValue != null) {
  returnValue = FetchXYCoordinate(parms);
 }

 return returnValue;
}

谢谢!

【问题讨论】:

    标签: c# design-patterns oop


    【解决方案1】:

    Chain of responsability

    每个处理对象都包含一组逻辑,描述了它可以处理的命令对象的类型,以及如何将那些它不能处理的对象传递给链中的下一个处理对象

    所以你定义和抽象 SearchSystem (或 SystemSearch )并添加这样的子类:

    class SearchSystem
    {
        //link to the next in the chain 
        SearchSystem next;
    
        // Basic search, If cannot handle forward to the next.
        public Result search( Criteria c ) 
        {
            Result r = doSearch( c );
    
            if( r != null ) 
            {
                return r;
            }
    
            return next.search( c );
        }
        // subclass specific system search
        abstract Result doSearch( Criteria c );
    }
    
    class SearchSystemOne: SearchSystem 
    {
        Result doSearch( Criteria c )
        {
            // do some system 1 speficif stuff 
            // and return either and instance or null
        }
    }
    class SearchSystemTwo: SearchSystem 
    {
        Result doSearch( Criteria c )
        {
            // do some system 2 speficif stuff 
            // and return either and instance or null
        }
    }
    .... etc etc. 
    // End of the chain
    class SearchSystemOver: SearchSystem 
    {
        public Result search( Criteria c ) 
        {
            throw new ApplicationException("Criteria not foud", c );
        }
        Result doSearch( Criteria c )
        {
           // didn't we throw exception already?
        }
    }
    

    实例化

    SearchSystem one = new SearchSystemOne();
    SearchSystem two = new SearchSystemTwo();
    SearchSystem three = new SearchSystemThree();
    SearchSystem four = new SearchSystemFour();
    SearchSystem over = new SearchSystemOver();
    

    并建立链

    one.next = two;
    two.next = three;
    three.next = four;
    four.next = over;
    

    最后搜索一下。

    SearchSystem searcher = one;
    
    searcher.search( Criteria.addName("Oscar").addLastName("Reyes"));
    

    【讨论】:

    • 这似乎有点矫枉过正,因为需求没有指定动态构建链的需要,这是 CoR 的核心优势。另外,这条链应该在哪里定义?
    • 我喜欢这个实现,但是在 SearchSystem1 中有基于条件的条件流。此外,有时如果在一个系统中发现它,这意味着我们想从另一个系统收集额外的数据。不确定如何在 Chain 中表达这一点,因为您可以返回 null 或 Result。
    • 很难说,你为什么不把代码贴出来看看是怎么回事
    【解决方案2】:

    可能是Strategy Pattern

    它允许您抽象出用于执行逻辑的算法,将它们封装在它们自己的对象中,然后在整个应用程序中互换使用它们(允许调用者定义要使用的算法)。

    【讨论】:

      【解决方案3】:

      我可能会在这里通过为搜索系统定义一个接口来使用策略模式:

      public interface ISearchStrategy
      {
          string Search(string criteria);
      }
      

      然后将它们传递给 validate 方法(尽管验证类可以从其他地方获取它们)。

      public string Validate(string parms, IEnumerable<ISearchStrategy> searchStrategies)
      {
          string returnValue = null;
      
          foreach(var strategy in searchStrategies)
          {
              if(returnValue == null)
              {
                  returnValue = strategy.Search(parms);
              }
          }
      
          if(returnValue == null) throw new ApplicationException("ID invalid");
          return returnValue;
      }
      

      【讨论】:

        【解决方案4】:

        在不了解您的域的情况下,我只能建议进行细微的调整。首先是使用guard clauses

        您还提到 SearchSystems 需要知道如何构建业务对象。我会确保 SearchSystems 可以被多态处理(这样你就有了重构策略或某种依赖注入的路径)。此外,我更喜欢 SystemSearcher 而不是一系列 SearchSystem 方法。然后我会在 SearchSystems 中注入一个业务对象工厂。我还会使用 TryXXX 语义设计行为。

        public interface ISearchSystem
        {
          bool TryGet(string parms, out string businessObject);
        }
        
        public class System1Searcher : ISearchSystem
        {
          public System1Searcher(BusinessObjectFactory factory) { _factory = factory; }
          private field BusinessObjectFactory _factory;
          public bool TryGet(string parms, out string businessObject)
          {
            // do internal logic
            return _factory.Create(string stuff);
          }
        }
        
        public class Service
        {
          // is "Validate" the correct metaphor for this logic?
          public string Validate(string parms) 
          {
            string returnValue = null;
            if (new System1Searcher().TryGet(parms, out returnValue)
              return returnValue;
        
            if (new System2Searcher().TryGet(parms, out returnValue)
              return returnValue;
        
            if (new System3Searcher().TryGet(parms, out returnValue)
              return returnValue;
        
            if (new System4Searcher().TryGet(parms, out returnValue)
              return returnValue;
        
            // this message should be written in terms of the logic of this method
            // such as "Parameters invalid"
            throw new ApplicationException("ID Invalid"); 
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2019-10-10
          • 2015-11-09
          • 1970-01-01
          • 1970-01-01
          • 2013-02-18
          • 2010-09-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多