0

((a > b OR c == d) AND e < f) などの論理条件をモデル化するのに役立つ設計パターンまたは適切なアプローチはありますか? 特に、オブジェクト プログラミングを使用して、括弧と OR/AND を柔軟に定義する方法に興味があります。

4

2 に答える 2

0

どのように使用する予定かについてもう少し知っておくと役立ちますが、試してみます。リーフノードと複合ノードを分離することで複雑な論理条件を表すことができます。リーフノードは、非再帰的な処理に基づいてtrue / falseに評価できるものを表しますが、複合ノードは、評価を子に委任してから、何らかの関数を適用して最終的な値を算出します。

例として、この設計を考えてみましょう。

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();

注目に値するいくつかのこと:

  • これは、コンポジットパターンの単なる実現です。それがどのように機能するかをよりよく理解するためにそれを見てください。
  • この設計は単なる例です。子ノードのコレクション(一般化されたANDなど)を使用して、単項演算子(NOTなど)、より多くのバイナリ(AND、OR)、またはN-aryを使用できます。
  • 抽象Nodeクラスはインターフェースである可能性があるため、新しいノードを特定の階層の兄弟にすることを回避できます。
  • これを使用しているコンテキストはわかりませんが、コマンドパターンによって興味深いアイデアが得られる場合もあります。

HTH

于 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>

もう 1 つの方法は、ビジター パターンを使用して、ノードを解釈するためのロジックを、ノード タイプをオンにする外部ビジターに入れることです。

于 2012-12-04T13:40:41.930 に答える