July 16, 2018
Hot Topics:

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) {
      this.length = length;

   public int getLength() {
      return length;

   public String sqlValue(Object value) {
      return "'" + value + "'";
public class NumericColumn extends Column {
   public NumericColumn(String 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 {
   public void stringColumn() {
      Column column = new StringColumn("name", 10);
      Equals criteria = new Equals(column, "joe");
      assertEquals("name = 'joe'", criteria.sqlString());

   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 {
   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.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

By submitting your information, you agree that developer.com may send you developer offers via email, phone and text message, as well as email offers about other products and services that developer believes may be of interest to you. developer will process your information in accordance with the Quinstreet Privacy Policy.


Thanks for your registration, follow us on our social networks to keep up-to-date