Builder

Introduction

Builder pattern is used to isolate the code from the construction and representation. Unlike Abstract Factory pattern and Factory Method pattern whose intention is to enable polymorphism, the intention of Builder pattern is to find a solution to telescoping constructor anti-pattern.

Definition

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

UML class Diagram

Builder pattern

Participants

  • Builder
    • specifies an abstract interface for creating parts of Product object.
  • ConcreteBuilder
    • construts and assembles parts of the product by implementing the Builder interface.
    • defines and keeps track of the representations it creates.
    • provides an interface for retrieving the product.
  • Director
    • constructs an object using the Builder interface.
  • Product
    • represents the complex object under construction. ConcreteBuilder builds the product’s internal representations and defined the process by which it’s assembled.
    • includes classes that define the consitituent parts, including interfaces for assembling the parts into final result.

Example

Here is an example, which use Builder pattern to build a Message object.

// Message
public class Message {
	private String 			content;
	private List<String> 	targetList;
	private Date time;

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public List<String> getTargetList() {
		return targetList;
	}

	public void setTargetList(List<String> targetList) {
		this.targetList = targetList;
	}

	public Date getTime() {
		return time;
	}

	public void setTime(Date time) {
		this.time = time;
	}
}

// Abstract MessageBuilder
public abstract class MessageBuilder {
	protected Message mMessage = new Message();

	public abstract void buildContent();

	public abstract void buildTarget();

	public abstract void buildDate();

	public Message getMessage() {
		return mMessage;
	}
}

// Concrete MessageBuilder 
public class MailMessageBuilder extends MessageBuilder {

	@Override
	public void buildContent() {
		// TODO Auto-generated method stub
		mMessage.setContent("MailSenderBuilder...");
	}

	@Override
	public void buildTarget() {
		// TODO Auto-generated method stub
		List<String> targetList = new ArrayList<String>(0);
		targetList.add("test1@test.com");
		targetList.add("test2@test.com");
		mMessage.setTargetList(targetList);
	}

	@Override
	public void buildDate() {
		// TODO Auto-generated method stub
		Date date = new Date();
		mMessage.setTime(date);
	}

}

public class SmsMessageBuilder extends MessageBuilder {

	@Override
	public void buildContent() {
		// TODO Auto-generated method stub
		mMessage.setContent("SmsSenderBuilder...");
	}

	@Override
	public void buildTarget() {
		// TODO Auto-generated method stub
		List<String> targetList = new ArrayList<String>(0);
		targetList.add("+86130-0000-0000");
		targetList.add("+86138-1234-5678");
		mMessage.setTargetList(targetList);
	}

	@Override
	public void buildDate() {
		// TODO Auto-generated method stub
		Date date = new Date();
		mMessage.setTime(date);
	}

}

// Message Director
public class MessageDirector {
	public Message createMessage(MessageBuilder builder) {
		builder.buildContent();
		builder.buildTarget();
		builder.buildDate();
		return builder.getMessage();
	}
}

// Test Case
public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String builderType = "mail";
		MessageDirector director = new MessageDirector();
		MessageBuilder builder = null;
		
		if (builderType.equalsIgnoreCase("mail")) {
			builder = new MailMessageBuilder();
		} else if (builderType.equalsIgnoreCase("sms")) {
			builder = new SmsMessageBuilder();
		} else {
			// TODO another builders...
		}
		
		Message message = director.createMessage(builder);
		//.... 
	}
}

The construction process is MessageDirector, it creates different representations which are created in the ~Builder class. The ~Builder is responsible for representations.

Usage

  • The algorithm for creating a complex object should be independent of both the parts that make up the object and how the parts are assembled.
  • The construction process must allow different representations of the constructed object.

See Also

blog comments powered by Disqus