Some imaginary company has very funny business, when people have garage sales, they go and buy everything they can fit into few of their trucks. In the end of the day they are very interested to know how much goods inside of each of the trucks cost. We don’t really care what they do after. But we are interested in knowing how they calculate cost of goods. Many things they buy are packed into packages, sometimes they put similar goods into one package, sometimes they double-triple pack fragile things. So company deals with trucks stuffed with packages of goods. The other day truck's guts can hit different cost number. In the context of current date prices, having graph of packages/goods we can calculate total cost, this can be done by man, but company goes different way, trucks do it automatically. Each truck accumulates cost of each package, each package calculates cost of what’s inside (packages/goods), any stuff knows its today’s price. // Abstract expression
public abstract class Goods
{
public abstract int Interpret(CurrentPricesContext context);
}
// Nonterminal expression
public class GoodsPackage : Goods
{
public List<Goods> GoodsInside { get; set; }
public override int Interpret(CurrentPricesContext context)
{
var totalSum = 0;
foreach (var goods in GoodsInside)
{
totalSum += goods.Interpret(context);
}
return totalSum;
}
}
// Terminal expression
internal class TV : Goods
{
public override int Interpret(CurrentPricesContext context)
{
int price = context.GetPrice("TV");
Console.WriteLine("TV: {0}", price);
return price;
}
}
// Here other terminal expressions go (Laptop, Bed)
public void RunInterpreterDemo()
{
// create syntax tree that represents sentence
var truckWithGoods = PrepareTruckWithGoods();
// get latest context
var pricesContext = GetRecentPricesContext();
// invoke Interpret
var totalPriceForGoods = truckWithGoods.Interpret(pricesContext);
Console.WriteLine("Total: {0}", totalPriceForGoods);
}
private CurrentPricesContext GetRecentPricesContext()
{
var pricesContext = new CurrentPricesContext();
pricesContext.SetPrice("Bed", 400);
pricesContext.SetPrice("TV", 100);
pricesContext.SetPrice("Laptop", 500);
return pricesContext;
}
public GoodsPackage PrepareTruckWithGoods()
{
var truck = new GoodsPackage() { GoodsInside = new List<Goods>() };
var bed = new Bed();
var doubleTriplePackedBed = new GoodsPackage() { GoodsInside = new List<Goods>() { new GoodsPackage() { GoodsInside = new List<Goods>() { bed } } } };
truck.GoodsInside.Add(doubleTriplePackedBed);
truck.GoodsInside.Add(new TV());
truck.GoodsInside.Add(new TV());
truck.GoodsInside.Add(new GoodsPackage() { GoodsInside = new List<Goods>() { new Laptop(), new Laptop(), new Laptop() } });
return truck;
}
Quickly output:Bed: 400
TV: 100
TV: 100
Laptop: 500
Laptop: 500
Laptop: 500
Total: 2100
Interpreter is one of the design patterns that you most likely will never use in your life. It is bit cumbersome and has very specific application.
My Design Patterns Table

