C# 我怎样才能在不严重破坏模式的情况下重构它来工作?

C# 我怎样才能在不严重破坏模式的情况下重构它来工作?,c#,.net,design-patterns,C#,.net,Design Patterns,我有一个用于过滤的基类对象。它是一个模板方法对象,看起来像这样 public class Filter { public void Process(User u, GeoRegion r, int countNeeded) { List<account> selected = this.Select(u, r, countNeeded); // 1 List<account> filtered = this.Filter(s

我有一个用于过滤的基类对象。它是一个模板方法对象,看起来像这样

public class Filter
{
    public void Process(User u, GeoRegion r, int countNeeded)
    {
        List<account> selected = this.Select(u, r, countNeeded); // 1
        List<account> filtered = this.Filter(selected, u, r, countNeeded); // 2

        if (filtered.Count > 0) { /* do businessy stuff */ } // 3

        if (filtered.Count < countNeeded)
            this.SendToSuccessor(u, r, countNeeded - filtered) // 4
    }
}

我该怎么做呢?

您可以将过滤器实现为。事实上,在过滤器中调用后继对象的方式与Decorator完全相同,所以为什么不完全实现该模式呢。主要的区别在于,后继者是在构造函数中传递的。然后你可以像这样把它们连在一起:

Filter f3 = new Filter3();
Filter f2 = new Filter2(f3);
Filter f = new Filter1(f2);

foreach (User u in users)
{
    foreach (GeoRegion r in regions)
    {
        f.Process(u, r, ##);
    }
}
class SuperFilter : Filter
{
    private object more, parameters, here;
    public SuperFilter(object more, object parameters, object here)
    {
        this.more = more;
        this.parameters = parameters;
        this.here = here;
    }
    override protected List<account> Filter(selected, u, r, countNeeded)
    {
        // use more parameters here along with the regular parameters
    }
    ...
}
  public class GregorianFilterCommand<T>: FilterCommand where T is IBusinessEntity
  {
     public GregorianFilterCommand(IList<T> rawDataList, .....);

     public IList<T> Execute();
     .........
  }
您可能很清楚,可以将模板方法嵌入到:一个公共基接口,每个不同过滤器集的抽象通用模板方法子类,然后是每个过滤器集的具体实现子类

困难的部分是不同的参数集。如果您想使用新的过滤器与旧的过滤器透明地混合使用,它们应该具有相同的接口,因此它们都应该获得(并向前传递)所有现有参数的超集,这在4-5个参数的计数中迅速变得难看

一种可能是在每个筛选器的构造函数中传递特殊参数,并将公共参数传递给
进程
,但这很困难,因为在一个循环中有许多次运行时使用了不同的参数。。。除非您可以将整个嵌套的
foreach
循环移动到过滤器内,然后将
用户
区域
作为参数:

public class Filter
{
    private UserCollection users;
    private GeoRegionCollection regions;

    public void Process(UserCollection users, GeoRegionCollection regions)
    {
        this.users = users;;
        this.regions = regions;
    }

    public void Process()
    {
        foreach (User u in users)
        {
            foreach (GeoRegion r in regions)
            {
                Process(u, r, ##);
            }
        }
    }

    public void Process(User u, GeoRegion r, int countNeeded)
    {
        // as before
    }
}
另一种可能是将这些参数组合在一个通用结构中,该结构具有足够的可变性来容纳不同的参数集。但通常情况下,最终会出现一些丑陋的映射式存储,您需要按名称查找参数,然后将其向下转换为正确的类型:-(


在不知道更多细节的情况下,很难说更多…

您能将进入筛选的片段作为一个集合传递吗?保持所有其他内容不变,但有一个可能的筛选参数集合,每个子类都知道如何处理这些参数。

为什么不想用一个方法
void进程定义接口
IFilter
(用户u,georgion r,int countNeeded)
然后抽象类
FilterType1
(使用抽象方法
Select
Filter
),使用两个派生类和另一个类
Filter3
(只需实现
过程
方法)?

听起来您想要做的是调用this.Filter(selected,u,r,countNeeded,more,parameters,here);。如果是这样,您可以将附加参数作为参数实现到构造函数中,并存储为私有成员字段,如下所示:

Filter f3 = new Filter3();
Filter f2 = new Filter2(f3);
Filter f = new Filter1(f2);

foreach (User u in users)
{
    foreach (GeoRegion r in regions)
    {
        f.Process(u, r, ##);
    }
}
class SuperFilter : Filter
{
    private object more, parameters, here;
    public SuperFilter(object more, object parameters, object here)
    {
        this.more = more;
        this.parameters = parameters;
        this.here = here;
    }
    override protected List<account> Filter(selected, u, r, countNeeded)
    {
        // use more parameters here along with the regular parameters
    }
    ...
}
  public class GregorianFilterCommand<T>: FilterCommand where T is IBusinessEntity
  {
     public GregorianFilterCommand(IList<T> rawDataList, .....);

     public IList<T> Execute();
     .........
  }
类超级过滤器:过滤器
{
私有对象更多,参数,这里;
公共超级过滤器(对象更多,对象参数,此处的对象)
{
这个。更多=更多;
此参数=参数;
this.here=这里;
}
覆盖受保护列表筛选器(所选、u、r、CountRequired)
{
//在此处与常规参数一起使用更多参数
}
...
}

既然过滤器接受不同的参数,并且它总是必须对一组数据执行并返回所需的结果,为什么不使用命令模式呢

具有不同的命令类型,每个命令类型接受不同的参数集,并且始终让方法执行或处理您调用的过程,并始终返回一组数据。我假设您始终处理一组固定的数据,否则您甚至可以使用泛型和约束返回类型,如下所示:

Filter f3 = new Filter3();
Filter f2 = new Filter2(f3);
Filter f = new Filter1(f2);

foreach (User u in users)
{
    foreach (GeoRegion r in regions)
    {
        f.Process(u, r, ##);
    }
}
class SuperFilter : Filter
{
    private object more, parameters, here;
    public SuperFilter(object more, object parameters, object here)
    {
        this.more = more;
        this.parameters = parameters;
        this.here = here;
    }
    override protected List<account> Filter(selected, u, r, countNeeded)
    {
        // use more parameters here along with the regular parameters
    }
    ...
}
  public class GregorianFilterCommand<T>: FilterCommand where T is IBusinessEntity
  {
     public GregorianFilterCommand(IList<T> rawDataList, .....);

     public IList<T> Execute();
     .........
  }
公共类GregorianFilterCommand:FilterCommand,其中T是IBusinessEntity
{
公共GregorianFilterCommand(IList rawDataList,…);
公共IList Execute();
.........
}

> p>我会考虑使用一个小的重构来使用(如果可能的话)截取过滤器模式。< /P>
如果这不起作用,因为您无法为所有过滤器提供一个公共接口,您可以在前端控制器()周围使用装饰器模式,甚至可以应用非常抽象的责任链模式。

问题是,新的过滤器类型需要不同的参数作为f.Process(…)而不是u/r/##