Sunday, 9 February 2014

Interpreter Design pattern - Implementation [Date]

Master Practical Java Architecture & Design Patterns!

Subscribe to Ram N Java for clean coding tutorials, GoF design patterns, and real-world system implementations!

🔔 Subscribe to Ram N Java

The Date Parsing Challenge

In software engineering, handling and parsing string inputs conforming to specific grammatical rules—such as distinct date format representations (e.g., YYYY-MM-DD, DD-MM-YYYY, or MM-DD-YYYY)—frequently leads to complex, hard-coded string manipulation logic.

When applications attempt to parse dynamic expressions using endless conditional ladders, regular expressions, or custom string splits, the code quickly becomes brittle, difficult to test, and resistant to formatting extensions.

Applying the Interpreter Pattern to Date Formats

The Interpreter Design Pattern provides an elegant, object-oriented solution by defining a grammar for the language and using an interpreter to evaluate sentences within that grammar. In a practical date parsing implementation, each format token is represented as an expression:

  • Abstract Expression: Defines an interpret(Context context) interface common to all syntax nodes.
  • Terminal Expressions: Concrete implementations that interpret specific atomic tokens—such as year (YYYY), month (MM), and day (DD) elements.
  • Context: Holds the input date string and the current state or output being constructed during the interpretation process.
  • Client: Builds the abstract syntax tree (AST) representing the target date format and triggers the interpretation flow.

Key Architectural Benefits

Structuring parsing logic using the Interpreter pattern offers significant design advantages:

  • Extensible Grammar: Adding support for new date tokens (like hours, minutes, or day names) is as simple as defining a new terminal expression class without modifying existing parsers.
  • Single Responsibility Principle: Each token parser encapsulates its own formatting and extraction rules in an isolated, unit-testable class.
  • Maintainable Rule Engines: Eliminates hardcoded formatting trees in favor of a clean, composable object structure.

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=sBx4bw1T4Ek

Click the below Image to Enlarge
Interpreter Design pattern - Implementation [Date]















Interpreter Design pattern - Implementation [Date] - Class Diagram


Context.java

import java.util.Date;

public class Context
{
public String expression;
public Date   date;

public String getExpression()
{
return expression;
}

public void setExpression( String expression )
{
this.expression = expression;
}

public Date getDate()
{
return date;
}

public void setDate( Date date )
{
this.date = date;
}

}


AbstractExpression.java

public abstract class AbstractExpression
{
public abstract void evaluate( Context context );
}

DayExpression.java

import java.util.Date;

public class DayExpression extends AbstractExpression
{

@Override
public void evaluate( Context context )
{
String expression = context.getExpression();
Date date = context.getDate();
Integer day = new Integer(date.getDate());
String tempExpression = expression.replaceAll("DD", day.toString());
context.setExpression(tempExpression);
}
}

MonthExpression.java

import java.util.Date;


public class MonthExpression extends AbstractExpression
{

@Override
public void evaluate( Context context )
{
String expression = context.getExpression();
Date date = context.getDate();
Integer month = new Integer(date.getMonth()+1);
String tempExpression = expression.replaceAll("MM", month.toString());
context.setExpression(tempExpression);
}

}

YearExpression.java

import java.util.Date;

public class YearExpression extends AbstractExpression
{

@Override
public void evaluate( Context context )
{
String expression = context.getExpression();
Date date = context.getDate();
Integer year = new Integer(date.getYear() + 1900);
String tempExpression = expression.replaceAll("YYYY", year.toString());
context.setExpression(tempExpression);
}

}


Client.java

import java.util.ArrayList;
import java.util.Date;
import java.util.Scanner;

public class Client
{

public static void main( String[] args )
{

System.out.println("Please select the Expression  : 'MM-DD-YYYY' or 'YYYY-MM-DD'");
Scanner scanner = new Scanner(System.in);
String expression = scanner.next();

Context context = new Context();
context.setExpression(expression);
context.setDate(new Date());

ArrayList<AbstractExpression> expressionOrderList = getExpressionOrder(context);

System.out.println("Input : " + context.getExpression() + " : " + new Date());

for( AbstractExpression abstractExpression : expressionOrderList )
{
abstractExpression.evaluate(context);
System.out.println(abstractExpression.getClass().getName() + " Evaluated     : "
               + context.getExpression());

}

System.out.println("Output : " + context.getExpression());
}

private static ArrayList<AbstractExpression> getExpressionOrder( Context context )
{
ArrayList<AbstractExpression> expressionOrderList = new ArrayList<AbstractExpression>();
String[] strArray = context.getExpression().split("-");
for( String string : strArray )
{
if( string.equalsIgnoreCase("MM") )
{
expressionOrderList.add(new MonthExpression());
}
else if( string.equalsIgnoreCase("DD") )
{
expressionOrderList.add(new DayExpression());
}
else
{
expressionOrderList.add(new YearExpression());
}

}
return expressionOrderList;
}

}

Output

Please select the Expression  : 'MM-DD-YYYY' or 'YYYY-MM-DD'
MM-DD-YYYY
Input : MM-DD-YYYY : Sun Feb 09 22:23:45 IST 2014
MonthExpression Evaluated     : 2-DD-YYYY
DayExpression Evaluated     : 2-9-YYYY
YearExpression Evaluated     : 2-9-2014
Output : 2-9-2014

Please select the Expression  : 'MM-DD-YYYY' or 'YYYY-MM-DD'
YYYY-MM-DD
Input : YYYY-MM-DD : Sun Feb 09 22:23:55 IST 2014
YearExpression Evaluated     : 2014-MM-DD
MonthExpression Evaluated     : 2014-2-DD
DayExpression Evaluated     : 2014-2-9
Output : 2014-2-9

See also:

  • Interpreter Design pattern - Introduction
  • Interpreter Design pattern - Real time example [Google Translator]
  • Interpreter Design pattern - Real time example [JVM]
  • Interpreter Design pattern - Class Diagram
  • Interpreter Design pattern - Key points
  • All Design Patterns Links
  • No comments:

    Post a Comment

    Tutorials