3

所以我想做以下事情,我真的只是在寻找关于如何设计它的建议。

  • 我有Filter可以在某些实体类型上运行的 s
  • Filter必须Rule定义自己的行为
  • Filters 处理实体,使用它们的规则,并返回一个布尔值
  • 作为一个具体的例子,我可能想过滤掉给定字段上的某些正则表达式被拒绝,我可以为它定义规则。我也可以有不同的规则,在同一个过滤器中使用简单的前缀匹配。

所以我想出了以下内容

interface FilterInterface
{
    /**
     * Load the rules for this filter
     */
    function loadRules();

    /**
     * Filter an entity in an optional context
     * @param mixed $entity Should return true for $this->supportsEntity($entity)
     * @param array $context Other information
     * 
     * @return boolean True if the $entity passes this filter
     */
    function filter($entity, $context = array());

    /**
     * Check if filter supports the entity type
     * @param mixed $entity
     * 
     * @return boolean true if this Filter can be run for that entity type
     */
    function supportsEntity($entity);
}

然后我打算做:

class ImageFilter implements FilterInterface

这将从数据库中加载规则并实现过滤器。

所以最初我虽然有一个像

FilterRule

  • 范围(枚举类型来定义哪个过滤器使用它)
  • 类型(可以有不同类型的规则,比如我提到的正则表达式与前缀)
  • 值(字符串,取决于规则的类型)

并且会在范围设置为某个常量的地方ImageFilter加载s 。FilterRule然后ImageFilter会做繁重的检查过滤器类型并将其应用于实体,一个接一个。以下伪代码演示了这一点。

public function filter($entity)
{
    foreach ($this->rules as $rule) {
        switch($rule->getType()) {
            case RULE_TYPE_REGEX:
                $this->doRegex();
            break;
            case RULE_TYPE_PREFIX:
                $this->doPrefix();
            break;
        }
    }
}

但后来我想知道,该实体是否应该对上述switch区块负责?所以它会变成这样:

public function filter($entity)
{
    foreach ($this->rules as $rule) {
        $rule->process($entity);
    }
}

这对我来说似乎更干净,Filter只要“范围”正确,它就不关心新规则以及如何处理它们。 但我的印象是实体应该是简单的 POPO,所以看起来这种逻辑是一种不好的模式(但我从来没有 100% 确定实体应该真正做多少)。

我还考虑过使用继承映射,因此每个Rule“类型”都可以是不同的类,并且它的逻辑非常简单(最多只有几行)。最后,我在想也许不同类型的Rule应该以某种方式使用组合来产生“行为”或可以完成实际工作的东西......

所以总结一下,这是我目前的想法:

  1. Filter做所有的工作检查类型Rule并采取相应的行动。Rule只是一个“愚蠢”的实体来保存一些字符串
  2. Rule完成检查自己的类型并对给定实体做某事的所有工作。现在Rule实体有点“胖”但它隐藏了实现Filter并且Filter不需要更改以添加新Rule类型
  3. Rule使用继承来做上述,实际上是相同的想法,但没有更多的switch声明
  4. 2. 或 3. 但Rule为每种类型实例化不同的“行为”对象(不真正使用依赖注入似乎很糟糕,封装行为似乎是一个很好的设计)
  5. 结合 1. 和 4. 这样就Filter可以得到正确的行为Rule(现在可以像“行为”工厂一样使用依赖注入)

我想我越想越倾向于最后几个选项,但我不知道这方面的最佳实践。我确信这是一个相对常见的例子,所以我希望得到一些关于采取哪个方向的意见。(抱歉这么长的问题,希望它足够完整,可以回答)

4

1 回答 1

0

我从你在这里给出的解释中得到的是你有三个不同的东西-Rules和。所以,我会把这三个分开。FiltersRuleProcessing

Rules将只是定义过滤器的行为。

Filters将加载您想要做的规则和其他检查。

并将Rule Processing单独保存将取$entity$rule返回处理后的结果。那么你会得到这样的东西:

public function filter($entity)
{
    foreach ($this->rules as $rule) {
        RuleProcessing->processRule($entity, $rule);
    }
}

(如果我的理解在这里不正确,请告诉我。)

于 2015-04-21T12:53:06.143 回答