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.
INTERPRETER
Interpreter is design pattern that allows to represent language grammar and knows how to evaluate its sentences into parts that can be understood.
Talking about our dummy example, language would be truck/packages/goods, its current sentence would be stuffed truck ‘cause it has graph of language parts, and the meaning of the sentence would be total cost of the goods inside.
There are two kinds of expressions in the language, those that can be understood immediately, called terminal expressions, and those that require language logic to be applied to be understood, called nonterminal expressions.
Talking about our example, terminal expression would be old TV, Laptop or Bed, since we know that today old TV costs 100, Laptop 500 and Bed 400, and nonterminal expression would be package in which they put 3 laptops, where we have to apply logic to understand what it means to us.
Let’s take a look at our example source code:
Here are expressions our language contains:
    // 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)
As you can see GoodsPackage knows that for to be understood it has to accumulate cost of each things inside. In our example we have very simple language with only one rule for it, but in more complex languages we will have something different, like for math it could be (“+”, “-”, “/”, “*”, “Sqrt”, “Integral”, and so on…). Math would also have variety of terminal expressions, like numbers or variables, value of which can be substituted.
Two more things are left. It is context, which represent information global to the whole process, in our example prices as of today, and it is client, which actually somehow gets sentence and invokes method Interpret in order to understand sentence. Here below is only Client, I do not show CurrentPricesContext, since it would bring only noise to this example.
        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

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone