0

Is there a design pattern or a good approach that could help me to model a logical condition, such as ((a > b OR c == d) AND e < f). In particular, I'm interested in how I could use object programming to define parenthesis and OR/AND in a flexible way.

Car981
  • 261
  • 1
  • 3
  • 11

2 Answers2

0

Your expressions form a tree, so a direct representation would be to define an abstract expression class to represent the nodes of the tree, and define concrete subclasses for each operation e.g.

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

This puts the logic for the evaluation in the nodes. This makes adding new node types straightforward, since you can simply define a new subclass of Expr<T>.

Another approach is to use the Visitor Pattern to put the logic for interpreting nodes into an external visitor which switches on the node types.

Lee
  • 142,018
  • 20
  • 234
  • 287
0

It would help to know a little more about how are you planning to use it, but I'll give it a shot: you can represent a complex logical condition by separating leaf nodes and composite nodes. Leaf nodes would represent things that can be evaluated to true/false based on non-recursive treatment, while composite nodes will delegate the evaluation to their children and then apply some function to come up with the final value.

As an example consider this design:

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

and then you can create a new logic expression like this:

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

Some things worth noticing:

  • This is just a realization of the Composite pattern. Take a look at it for better understanding of how it works.
  • This desing is just an example. You can take it to have unary operators (e.g. NOT), more binary (AND, OR) or N-ary by using a collection of child nodes (e.g. a generalized AND)
  • The abstract Node class could be an interface, so you could avoid forcing new nodes to be siblings of a particular hierarchy.
  • I don't know the context in which you are using this, but the Command pattern may also give you some interesting ideas.

HTH

Andrés Fortier
  • 1,705
  • 11
  • 12