. Java Design Patterns

Java Design Patterns Interpreter

Interpreter Overview

Define a macro language and syntax, parsing input into objects which perform the correct opertaions.




DvdInterpreterClient.java - the Client

import java.util.StringTokenizer;

public class DvdInterpreterClient { DvdInterpreterContext dvdInterpreterContext; public DvdInterpreterClient( DvdInterpreterContext dvdInterpreterContext) { this.dvdInterpreterContext = dvdInterpreterContext; } // expression syntax: // show title | actor [for actor | title ] public String interpret(String expression) { StringBuffer result = new StringBuffer("Query Result: "); String currentToken; StringTokenizer expressionTokens = new StringTokenizer(expression); char mainQuery = ' '; char subQuery = ' '; boolean forUsed = false; String searchString = null; boolean searchStarted = false; boolean searchEnded = false; while (expressionTokens.hasMoreTokens()) { currentToken = expressionTokens.nextToken(); if (currentToken.equals("show")) { continue; //show in all queries, not really used } else if (currentToken.equals("title")) { if (mainQuery == ' ') { mainQuery = 'T'; } else { if ((subQuery == ' ') && (forUsed)) { subQuery = 'T'; } } } else if (currentToken.equals("actor")) { if (mainQuery == ' ') { mainQuery = 'A'; } else { if ((subQuery == ' ') && (forUsed)) { subQuery = 'A'; } } } else if (currentToken.equals("for")) { forUsed = true; } else if ((searchString == null) && (subQuery != ' ') && (currentToken.startsWith("<"))) { searchString = currentToken; searchStarted = true; if (currentToken.endsWith(">")) { searchEnded = true; } } else if ((searchStarted) && (!searchEnded)) { searchString = searchString + " " + currentToken; if (currentToken.endsWith(">")) { searchEnded = true; } } }

if (searchString != null) { searchString = searchString.substring(1,(searchString.length() - 1)); //remove <> } DvdAbstractExpression abstractExpression; switch (mainQuery) { case 'A' : { switch (subQuery) { case 'T' : { abstractExpression = new DvdActorTitleExpression(searchString); break; } default : { abstractExpression = new DvdActorExpression(); break; } } break; } case 'T' : { switch (subQuery) { case 'A' : { abstractExpression = new DvdTitleActorExpression(searchString); break; } default : { abstractExpression = new DvdTitleExpression(); break; } } break; } default : return result.toString(); } result.append( abstractExpression.interpret(dvdInterpreterContext)); return result.toString(); } }
download source, use right-click and "Save Target As..." to save with a .java extension.


DvdInterpreterContext.java - The Context

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdInterpreterContext { private ArrayList titles = new ArrayList(); private ArrayList actors = new ArrayList(); private ArrayList titlesAndActors = new ArrayList(); public void addTitle(String title) { titles.add(title); } public void addActor(String actor) { actors.add(actor); } public void addTitleAndActor(TitleAndActor titleAndActor) { titlesAndActors.add(titleAndActor); } public ArrayList getAllTitles() { return titles; } public ArrayList getAllActors() { return actors; } public ArrayList getActorsForTitle(String titleIn) { ArrayList actorsForTitle = new ArrayList(); TitleAndActor tempTitleAndActor; ListIterator titlesAndActorsIterator = titlesAndActors.listIterator(); while (titlesAndActorsIterator.hasNext()) { tempTitleAndActor = (TitleAndActor)titlesAndActorsIterator.next(); if (titleIn.equals(tempTitleAndActor.getTitle())) { actorsForTitle.add(tempTitleAndActor.getActor()); } } return actorsForTitle; } public ArrayList getTitlesForActor(String actorIn) { ArrayList titlesForActor = new ArrayList(); TitleAndActor tempTitleAndActor; ListIterator actorsAndTitlesIterator = titlesAndActors.listIterator(); while (actorsAndTitlesIterator.hasNext()) { tempTitleAndActor = (TitleAndActor)actorsAndTitlesIterator.next(); if (actorIn.equals(tempTitleAndActor.getActor())) { titlesForActor.add(tempTitleAndActor.getTitle()); } } return titlesForActor; } }
download source, use right-click and "Save Target As..." to save with a .java extension.


DvdAbstractExpression.java - The Abstract Expression

public abstract class DvdAbstractExpression {
   public abstract String interpret(
     DvdInterpreterContext dvdInterpreterContext);
}
download source, use right-click and "Save Target As..." to save with a .java extension.


DvdActorExpression.java - One Of Four Terminal Expressions

DvdActorExpression.java - One Of Four Terminal Expressions

import java.util.ArrayList; import java.util.ListIterator;

public class DvdActorExpression extends DvdAbstractExpression { public String interpret(DvdInterpreterContext dvdInterpreterContext) { ArrayList actors = dvdInterpreterContext.getAllActors(); ListIterator actorsIterator = actors.listIterator(); StringBuffer titleBuffer = new StringBuffer(""); boolean first = true; while (actorsIterator.hasNext()) { if (!first) { titleBuffer.append(", "); } else { first = false; } titleBuffer.append((String)actorsIterator.next()); } return titleBuffer.toString(); } }
download source, use right-click and "Save Target As..." to save with a .java extension.


DvdActorTitleExpression.java - Two Of Four Terminal Expressions

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdActorTitleExpression extends DvdAbstractExpression { String title; public DvdActorTitleExpression(String title) { this.title = title; } public String interpret(DvdInterpreterContext dvdInterpreterContext) { ArrayList actorsAndTitles = dvdInterpreterContext.getActorsForTitle(title); ListIterator actorsAndTitlesIterator = actorsAndTitles.listIterator(); StringBuffer actorBuffer = new StringBuffer(""); boolean first = true; while (actorsAndTitlesIterator.hasNext()) { if (!first) { actorBuffer.append(", "); } else { first = false; } actorBuffer.append((String)actorsAndTitlesIterator.next()); } return actorBuffer.toString(); } }
download source, use right-click and "Save Target As..." to save with a .java extension.


DvdTitleExpression.java - Three Of Four Terminal Expressions

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdTitleExpression extends DvdAbstractExpression { public String interpret(DvdInterpreterContext dvdInterpreterContext) { ArrayList titles = dvdInterpreterContext.getAllTitles(); ListIterator titlesIterator = titles.listIterator(); StringBuffer titleBuffer = new StringBuffer(""); boolean first = true; while (titlesIterator.hasNext()) { if (!first) { titleBuffer.append(", "); } else { first = false; } titleBuffer.append((String)titlesIterator.next()); } return titleBuffer.toString(); } }
download source, use right-click and "Save Target As..." to save with a .java extension.


DvdTitleActorExpression.java - Four Of Four Terminal Expressions

import java.util.ArrayList;
import java.util.ListIterator;

public class DvdTitleActorExpression extends DvdAbstractExpression { String title; public DvdTitleActorExpression(String title) { this.title = title; } public String interpret(DvdInterpreterContext dvdInterpreterContext) { ArrayList titlesAndActors = dvdInterpreterContext.getTitlesForActor(title); ListIterator titlesAndActorsIterator = titlesAndActors.listIterator(); StringBuffer titleBuffer = new StringBuffer(""); boolean first = true; while (titlesAndActorsIterator.hasNext()) { if (!first) { titleBuffer.append(", "); } else { first = false; } titleBuffer.append((String)titlesAndActorsIterator.next()); } return titleBuffer.toString(); } }
download source, use right-click and "Save Target As..." to save with a .java extension.


TitleAndActor.java - A Helper Class

public class TitleAndActor {
    private String title;
    private String actor;
    public TitleAndActor(String title, String actor) {
        this.title = title;
        this.actor = actor;
    }
    public String getTitle() {return this.title;}
    public String getActor() {return this.actor;}
} 
download source, use right-click and "Save Target As..." to save with a .java extension.


Try the Design Patterns Video Tutorial from SourceMaking

TestDvdInterpreter.java - testing the Interpreter

class TestDvdInterpreter {
    
   public static void main(String[] args) {
       DvdInterpreterContext dvdInterpreterContext = 
         new DvdInterpreterContext();
       dvdInterpreterContext.addTitle("Caddy Shack");
       dvdInterpreterContext.addTitle("Training Day");
       dvdInterpreterContext.addTitle("Hamlet");

dvdInterpreterContext.addActor("Ethan Hawke"); dvdInterpreterContext.addActor("Denzel Washington"); dvdInterpreterContext.addTitleAndActor( new TitleAndActor("Hamlet", "Ethan Hawke")); dvdInterpreterContext.addTitleAndActor( new TitleAndActor("Training Day", "Ethan Hawke")); dvdInterpreterContext.addTitleAndActor( new TitleAndActor("Caddy Shack", "Ethan Hawke")); dvdInterpreterContext.addTitleAndActor( new TitleAndActor("Training Day", "Denzel Washington")); DvdInterpreterClient dvdInterpreterClient = new DvdInterpreterClient(dvdInterpreterContext); System.out.println( "interpreting show actor: " + dvdInterpreterClient.interpret( "show actor")); System.out.println( "interpreting show actor for title : " + dvdInterpreterClient.interpret( "show actor for title ")); System.out.println( "interpreting show title: " + dvdInterpreterClient.interpret( "show title")); System.out.println( "interpreting show title for actor : " + dvdInterpreterClient.interpret( "show title for actor ")); } }
download source, use right-click and "Save Target As..." to save with a .java extension.


Test Results

interpreting show actor: 
  Query Result: Ethan Hawke, Denzel Washington
interpreting show actor for title : 
  Query Result: Ethan Hawke, Denzel Washington
interpreting show title: 
  Query Result: Caddy Shack, Training Day, Hamlet
interpreting show title for actor : 
  Query Result: Hamlet, Training Day, Caddy Shack

UML

UML for Interpreter

References


online
Portland Pattern Repository
Books
Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
Java Design Patterns - A Tutorial by James W. Cooper
Comments Comments are left by visitors to FluffyCat.com and may or may not be accurate.
Comment by markmontymark on 2008-04-16 Rate this Comment

replace the '<' char with &lt; and the '>' char with &gt; to display properly in HTML

Comment by archive on 2007-09-28 Rate this Comment

I realy appreciate the Java Patterns on your site. Since I like to play with the examples I simply copied it into text fils and compiled them. I found a few minor problems you may want to know about:

- null pointer exception for second example, I did
not yet try to find out what the real reason is.

interpreting show actor: Query Result: Ethan
Hawke,
Denzel Washington
Exception in thread "main"
java.lang.NullPointerException at
DvdInterpreterContext.getActorsForTitle(DvdInterpreterContext.java:24)
at
DvdActorTitleExpression.interpret(DvdActorTitleExpression.java:12)
at
DvdInterpreterClient.interpret(DvdInterpreterClient.java:106)
at
TestDvdInterpreter.main(TestDvdInterpreter.java:28)

Comment by archive on 2007-09-28 Rate this Comment

Ah, I also see now why the Interpreter example
gets a null pointer exception:

two lines in main() should contain the < >
construction:
dvdInterpreterClient.interpret("show actor for
title <Training Day>"));
...
dvdInterpreterClient.interpret("show title for actor
<Ethan Hawke>"));

However, since you show it in HTML, the browser is
not displaying it since it interprets them as
tags (which it does not know how to display)