0

是否有设计模式或好的方法可以帮助我对逻辑条件进行建模,例如 ((a > b OR c == d) AND e < f)。特别是,我对如何使用对象编程以灵活的方式定义括号和 OR/AND 感兴趣。

4

2 回答 2

0

更多地了解您打算如何使用它会有所帮助,但我会试一试:您可以通过分离叶节点和复合节点来表示复杂的逻辑条件。叶节点将表示可以基于非递归处理评估为真/假的事物,而复合节点会将评估委托给它们的子节点,然后应用一些函数来得出最终值。

例如,考虑这种设计:

abstract class Node
{
public abstract function eval();
}

class EqualNode extends Node
{
protected $aValue;
protected $bValue;

public function __construct($a, $b)
{
$this->aValue = $a;
$this->bValue = $b;
}

public function eval()
{
return $this->aValue == $this->bValue;
}
}

public class AndNode extends Node
{
protected $leftNode;
protected $rightNode;

public function __construct($left, $right)
{
$this->leftNode = $left;
$this->rightNode = $right;
}

public function eval()
{
return $this->leftNode->eval() && $this->rightNode->eval();
}
}

然后你可以像这样创建一个新的逻辑表达式:

$exp1 = new EqualNode(2,2);
$exp2 = new EqualNode('Hi','Bye');
$exp3 = new And($exp1, $exp2);
$exp3->eval();

一些值得注意的事情:

  • 这只是复合模式的一个实现。查看它以更好地了解它的工作原理。
  • 这个设计只是一个例子。您可以通过使用子节点的集合(例如广义与)将其具有一元运算符(例如 NOT)、更多二元运算符(AND、OR)或 N-ary
  • 抽象Node类可以是一个接口,因此您可以避免强制新节点成为特定层次结构的兄弟节点。
  • 我不知道您使用它的上下文,但命令模式也可能会给您一些有趣的想法。

高温高压

于 2012-12-04T13:55:19.530 回答
0

您的表达式形成一棵树,因此直接表示将是定义一个抽象表达式类来表示树的节点,并为每个操作定义具体的子类,例如

public abstract class Expr<T>
{
    public abstract T Eval();
}

public class Eq : Expr<bool>
{
    private Expr<int> left;
    private Expr<int> right;
    public Eq(Expr<int> left, Expr<int> right)
    {
        this.left = left;
        this.right = right;
    }

    public override bool Eval()
    {
        return this.left.Eval() == this.right.Eval();
    }
}

这将用于评估的逻辑放在节点中。这使得添加新节点类型变得简单,因为您可以简单地定义一个新的Expr<T>.

另一种方法是使用访问者模式将解释节点的逻辑放入打开节点类型的外部访问者中。

于 2012-12-04T13:40:41.930 回答