August 20, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Working with Design Patterns: Composite

  • July 2, 2007
  • By Jeff Langr
  • Send Email »
  • More Articles »

A composite is an object that can contain other objects. The composite pattern can be used in situations where client code can treat composites in the same manner as non-composites. In this example of the composite design pattern, I demonstrate how the need to express complex conditionals in SQL can be neatly fulfilled using the composite pattern. Individual, or "primitive," clauses, such as name like 'abc%', can be combined using conjunctions such as and. I can consider that an and expression is a composite clause that can consists of primitive clauses such as like.

To demonstrate how I can build up to a composite, I'll start by implementing my low-level needs. A Column object encapsulates the name of a column. Subclasses define any additional details required to construct various types of SQL statements. For example, the class StringColumn defines a length field that an SQL generator object might use to build a create table statement.

More importantly, the Column class defines an abstract method, sqlValue. Subclasses implement this method to return the value substring for an SQL where clause. For example, the SQL substring for the where clause where name = 'abc' would be "'abc'". Numeric columns, on the other hand, don't get embedded in single quotes (tics). The SQL value for where amount = 10 would be "10".

public abstract class Column {
   private String name;

   public Column(String name) {
      this.name = name;
   }

   String getName() {
      return name;
   }

   abstract String sqlValue(Object value);
}
public class StringColumn extends Column {
   private int length;

   public StringColumn(String name, int length) {
      super(name);
      this.length = length;
   }

   public int getLength() {
      return length;
   }

   public String sqlValue(Object value) {
      return "'" + value + "'";
   }
}
public class NumericColumn extends Column {
   public NumericColumn(String name) {
      super(name);
   }

   public String sqlValue(Object value) {
      return value.toString();
   }
}

With the Column hierarchy in place, it's easy to write a test that demonstrates how to construct the where clause for a simple equality comparison.

import static org.junit.Assert.*;
import org.junit.*;

public class EqualsTest {
   @Test
   public void stringColumn() {
      Column column = new StringColumn("name", 10);
      Equals criteria = new Equals(column, "joe");
      assertEquals("name = 'joe'", criteria.sqlString());
   }

   @Test
   public void numericColumn() {
      Column column = new NumericColumn("amount");
      Equals criteria = new Equals(column, 5);
      assertEquals("amount = 5", criteria.sqlString());
   }
}

The implementation:

public class Equals {
   private Column column;
   private Object value;

   public Equals(Column column, Object value) {
      this.column = column;
      this.value = value;
   }

   public String sqlString() {
      return String.format("%s = %s",
         column.getName(), column.sqlValue(value));
   }
}

That was pretty simple!

I now want to write a where clause that combines two EqualsCriteria, producing an SQL statement such as:

name = 'Joe' and amount = 10

The class AndTest lays out an example:

import static org.junit.Assert.*;
import org.junit.*;

public class AndTest {
   @Test
   public void and() {
      Equals name = new Equals(new StringColumn("name", 1), "Joe");
      Equals amount = new Equals(new NumericColumn("amount"), 5);
      And and = new And(name, amount);
      assertEquals("name = 'Joe' and amount = 5", and.sql());
   }
}

Again, a very simple implementation:

public class And {
   private Equals left;
   private Equals right;

   public And(Equals left, Equals right) {
      this.left = left;
      this.right = right;
   }

   public String sql() {
      return left.sqlString() + " and " + right.sqlString();
   }
}




Page 1 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel