0

我有一个过滤器列表。每个过滤器都有不同的职责并接受各种输入参数。界面如下所示:

void doFilter(Context context);

我运行它:

void main(){
  context.setA(input_for_filter_a);
  context.setB(input_for_filter_b);
  context.setC(input_for_filter_c);
  //...
  firstFilter.doFilter(context);
}

要添加过滤器,我必须

  1. 修改上下文,例如添加一个带有getter 和setter 的私有字段。

  2. 更新 main() 以填充新的输入参数。

有没有办法解耦所有这些输入参数,以便不同的过滤器可以专注于他们需要知道的每个参数。我希望 main() 中的代码可以稳定。谢谢!

PS 某些过滤器可能没有任何输入参数。

4

2 回答 2

0

Context您正在与Filter实现细节之间创建危险的依赖关系。在如此高的耦合下,您会遇到已经注意到的问题,例如,您需要更改Context,无论何时添加或更改Filter.

所有人Context都应该知道的Filter是,它有一个公共方法来执行其实现细节。仅此而已!该方法在Filter接口中定义。

Filter取决于 aContext的存在。它也知道如何处理它的参数。

要实现责任链,Context可以有一组Filter对象,它可以迭代并调用接口中定义的过滤方法。

在伪代码中它会是这样的:

class Filter {
  function Filter(context, params) {
    // initializes a filter object with a context and its specific parameters
  }

  function run() {
    // run is the method defined by the Filter interface
    // here goes the implementation details for this filter
  }
}


class Context {
  array filters = [];

  function applyFilter(filter) {
    filters.push(filter);
  }

  function run() {
    for filter in filters {
      // all a context needs to know is how to execute a filter
      filter.run
    }
  }
}

void main() {    
  context  = new Context();
  filter_a = new Filter(context, params_a);
  filter_b = new Filter(context, params_b);

  context.applyFilter(filter_a);
  context.applyFilter(filter_b);

  context.run();
}

我事先为伪代码道歉。根据您示例的语法,我猜您使用的是 Java 或 C++。我也不知道,但我尝试遵循相同的语法。

我希望这能对这个问题有所了解。让我知道我是否可以使任何事情更清楚。

最好的!

于 2014-09-02T17:37:10.663 回答
0

使用Map<Object, Object>作为上下文是不可接受的吗?这样您就可以将存储与逻辑分开。如果您希望算法仅访问它们各自的数据部分,请防止 Map 迭代。

如果您想要具有静态确保封装的类型安全解决方案,请使用角色对象模式(Facet 模式,有更好的名称吗?)来隔离不同算法的数据:

/** Unique identifier for context data **/
public static class FacetKey<T> {
  private final Class<T> type;
  public FacetKey(Class<T> type) {
    assert type != null;
    this.type = type;
  }
}

/** Holds typed data.
  * Only key holder can access data addressed by that key.
  **/
public static class Context {
  private final Map<FacetKey, Object> data = new HashMap<>();
  public <T> T put(FacetKey<T> key, T datum) {
    return key.type.cast(data.put(key, datum));
  }
  public <T> T get(FacetKey<T> key){
    return key.type.cast(data.get(key));
  }
}

class FilterC {
  // This key is unaccessible for other clasess
  // Only FilterC can manipulate with it data
  private static final FacetKey<Boolean> key = new FacetKey<Boolean>();
  public static void enable(Context context) {
    context.put(key, true);
  } 
  public static void disable(Context context) {
    context.put(key, false);
  }       
  public static boolean doFilter(Context context) {
    return context.get(key);
  }
}

public static void main (String[] args) throws java.lang.Exception
{
  Context context = new Context();
  context.put(FilterA.key, new DataA());
  context.put(DataBFactory.key, new DataB());
  println("" + new FilterA().apply(context));
  println("" + new FilterB().apply(context));
}

主要思想是在数据提供者和过滤器之间共享密钥,但对不需要访问此数据的各方隐藏它们。每个密钥都是唯一的,无法重新创建,因此访问数据的每一方都需要对密钥实例有一个显式引用,这很容易被编译器和静态分析控制。

完整的使用示例

于 2014-09-04T18:15:54.913 回答