During this lab session:
This activity helps the student develop the following skills, values and attitudes: ability to analyze and synthesize, capacity for identifying and solving problems, and efficient use of computer systems.
This lab can be developed individually or in pairs.
Make a new folder called visitor. Place all the files you
create in this folder.
What follows is one possible generic implementation of the Visitor Pattern using C#. This example basically allows representing trees of arithmetic expressions, similar to those seen in our previous class when we discussed the Interpreter Pattern.
namespace VisitorPattern {
public interface IVisitor<T> {
T Visit(Number<T> node);
T Visit(Plus<T> node);
T Visit(Times<T> node);
}
public interface INode<T> {
T Accept(IVisitor<T> visitor);
}
public class Number<T>: INode<T> {
public int Value { get; private set; }
public Number(int value) {
Value = value;
}
public T Accept(IVisitor<T> visitor) {
return visitor.Visit(this);
}
}
public abstract class BinaryOperator<T>: INode<T> {
public INode<T> Left { get; private set; }
public INode<T> Right { get; private set; }
public BinaryOperator(INode<T> left, INode<T> right) {
Left = left;
Right = right;
}
public abstract T Accept(IVisitor<T> visitor);
}
public class Plus<T>: BinaryOperator<T> {
public Plus(INode<T> left, INode<T> right): base(left, right) {}
public override T Accept(IVisitor<T> visitor) {
return visitor.Visit(this);
}
}
public class Times<T>: BinaryOperator<T> {
public Times(INode<T> left, INode<T> right): base(left, right) {}
public override T Accept(IVisitor<T> visitor) {
return visitor.Visit(this);
}
}
}
A specific visitor can now be implemented like this:
namespace VisitorPattern {
public class Eval: IVisitor<int> {
public int Visit(Number<int> node) {
return node.Value;
}
public int Visit(Plus<int> node) {
return node.Left.Accept(this) + node.Right.Accept(this);
}
public int Visit(Times<int> node) {
return node.Left.Accept(this) * node.Right.Accept(this);
}
}
}
Extend the given code in the following ways:
Less<T> (the
binary "less than" operator, that returns 1 when true, or 0
when false) and Condition<T> (a ternary
conditional operator).
InOrder and
PreOrder. Check the unit tests in order to
understand how these classes should work.
Make sure the code that you write behaves exactly as expected by the following unit tests:
namespace VisitorPattern {
using NUnit.Framework;
[TestFixture]
public class TestVisitor {
INode<int> intRoot;
INode<string> strRoot;
[SetUp]
public void Init() {
// if 2 + 2 < 2 * 2 then 2 + 3 * 4 else (2 + 3) * 4
intRoot =
new Condition<int>(
new Less<int>(
new Plus<int>(
new Number<int>(2),
new Number<int>(2)),
new Times<int>(
new Number<int>(2),
new Number<int>(2))),
new Plus<int>(
new Number<int>(2),
new Times<int>(
new Number<int>(3),
new Number<int>(4))),
new Times<int>(
new Plus<int>(
new Number<int>(2),
new Number<int>(3)),
new Number<int>(4)));
strRoot =
new Condition<string>(
new Less<string>(
new Plus<string>(
new Number<string>(2),
new Number<string>(2)),
new Times<string>(
new Number<string>(2),
new Number<string>(2))),
new Plus<string>(
new Number<string>(2),
new Times<string>(
new Number<string>(3),
new Number<string>(4))),
new Times<string>(
new Plus<string>(
new Number<string>(2),
new Number<string>(3)),
new Number<string>(4)));
}
[Test]
public void TestEval() {
Assert.AreEqual(20, intRoot.Accept(new Eval()));
}
[Test]
public void TestInOrder() {
Assert.AreEqual(
"(((2 + 2) < (2 * 2)) ? (2 + (3 * 4)) : ((2 + 3) * 4))",
strRoot.Accept(new InOrder()));
}
[Test]
public void TestPreOrder() {
Assert.AreEqual(
"(if (< (+ 2 2) (* 2 2)) (+ 2 (* 3 4)) (* (+ 2 3) 4))",
strRoot.Accept(new PreOrder()));
}
}
}
To hand in your lab work, follow these instructions:
readme.txt text file that includes the name
and student ID of the authors. Copy this file to the
visitor folder.
visitor directory. Call this file
visitor.zip.
This activity will be evaluated using the following criteria:
| 100 | The code works as requested. |
|---|---|
| 60-90 | The code works, but has some flaws. |
| 20-50 | The code doesn't work, but it seams that some amount of time was spent on it. |
| DA | The program was plagiarized. |