【问题标题】:Should We use NullValueFilter in Intercept Design Pattern Implementation?我们应该在拦截设计模式实现中使用 NullValueFilter 吗?
【发布时间】:2021-11-25 16:02:49
【问题描述】:

我有一个需要通过不同类型过滤器处理的广告系列列表,例如平台过滤器、应用程序过滤器、CampaignRunning 过滤器,以检查当前日期是否应介于开始日期和结束日期等之间。

理想情况下有 15 - 20 个不同的过滤器,我使用 Intercept Design Pattern 管理它们。

在应用过滤器之前列表可能为空,那么我应该在过滤器链中使用NullValueFilter 吗?

再次应用一些过滤器列表后可以为空,以检查我是否也应该使用策略设计模式注入相同的空或空检查策略?

我通常会更多地考虑设计视角来管理此类案例。我想知道我的想法是否正确,或者我在这方面过度设计了。

一些伪代码来说明场景 -

Class NullValueFilter : IFilter {
  Execute(List<CampaignList> campaignList) {
    if(campaignList != null && campaignList.Count == 0) {
         return false;
    }
    return true;
  }
}

Class PlatformFilter : IFilter {
  Execute(List<CampaignList> campaignList) {
    if(campaignList != null && campaignList.Count == 0) {
         return false;
    }
    campaignList = campaignList.Where( x => x.Platform == 'Mobile');
    return true
  }
}

Class CampaignRunningFilter : IFilter {
  Execute(List<CampaignList> campaignList) {
    if(campaignList != null && campaignList.Count == 0) {
         return false;
    }
    // first Fetch campaign start date and end date 
    
    campaignList = campaignList.Where( x => x.startdate <= curr_date && x.enddate >= curr_date);
    return true
  }
}

我可以在这里想到两个选项 -

  1. 创建一个过滤器基类,可以管理列表的空和空检查。
  2. 使用构造函数注入在每个过滤器中注入空值过滤器实例,并调用该空值和空值检查方法。

【问题讨论】:

  • @DocBrown 伪代码添加供您参考。
  • 好的,我看到你的“空值过滤器”没有过滤任何东西,它只是检查空列表,返回真或假。但是这将如何影响过滤呢?
  • ...和第二个问题:为什么所有这些检查都需要空列表?在我看来,如果没有检查,所有这些过滤器都可以正常工作:空列表输入给出空列表。
  • 首先,Null Value Filter 将只检查 null 并决定是否应该执行下一个过滤器或中断链。其次,我只想避免在空列表上执行下一个过滤器链。

标签: oop design-patterns object-oriented-analysis system-design architectural-patterns


【解决方案1】:

对于 15 到 20 个过滤器,我根本不会对空列表进行任何检查,这会使事情变得比必要的复杂而没有任何明显的好处。

每个过滤器在传递一个空列表时表现得完全一致,所以我看不出有什么令人信服的理由说明这种“断链”的过早优化是必要的。最干净的设计是恕我直言,我们将任何不必要的浪费都扔到了船上,所以这就是我要开始的设计。

但是,如果您真的注意到 可测量,通过在空列表处停止处理来提高相关性能,我不会让过滤器测试这种情况。相反,让调用者直接测试它,而不是检查布尔返回码。我建议让Execute 方法返回过滤后的列表,并按照以下 sn-p 的方式实现它:

 List<Campaign> campaignList = ...;  // init this here
 foreach(IFilter filter in GetActiveFilters)
 {
      if(campaignList==null || campaignList.Count == 0)
          break;
      campaignList = filter.Execute(campaignList);
 }

这样,代码中只有一个地方需要实现空列表测试,您不必在过滤器中一遍又一遍地重复。

【讨论】:

    【解决方案2】:

    我们可以创建一个抽象类来公开一个公共方法 Execute,它将负责调用另一个受保护的抽象方法让我们说 ExecuteFilter 并有条件地调用它,所有过滤器都将实现这个抽象类 例如:

    Class AbstractBaseFilterClass : IFilter {
        public Execute(List<CampaignList> campaignList) {
        if(campaignList != null && campaignList.Count == 0) {
             return false;
           }
          ExecuteFilter(campaignList);
       }
       protected abstract boolean ExecuteFilter(List<CampaignList> campaignList);
    }
    
    
    Class PlatformFilter : AbstractBaseFilterClass {
      ExecuteFilter(List<CampaignList> campaignList) {
        if(campaignList != null && campaignList.Count == 0) {
             return false;
        }
        campaignList = campaignList.Where( x => x.Platform == 'Mobile');
        return true
      }
    }
    
    Class CampaignRunningFilter : AbstractBaseFilterClass {
      ExecuteFilter(List<CampaignList> campaignList) {
        if(campaignList != null && campaignList.Count == 0) {
             return false;
        }
        // first Fetch campaign start date and end date 
        
        campaignList = campaignList.Where( x => x.startdate <= curr_date && x.enddate >= curr_date);
        return true
      }
    }
    
    // client can call it simply
     List<Campaign> campaigns = ...;
     foreach(IFilter filter in Filters)
     {
         filter.Execute(campaignList);
     }
    
    

    【讨论】:

      猜你喜欢
      • 2019-09-05
      • 1970-01-01
      • 2011-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多