Java/Design Pattern/Builder Pattern
Builder Pattern - Example
/*
Software Architecture Design Patterns in Java
by Partha Kuchana
Auerbach Publications
*/
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Calendar;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
public class SearchManager extends JFrame {
public static final String GET_SQL = "Get SQL";
public static final String EXIT = "Exit";
public static final String CANDIDATE_SRCH = "Candidate Search";
public static final String EMPLOYER_SRCH = "Employer Search";
public static final String BLANK = "";
private JComboBox cmbSearchType;
private JPanel pSearchCriteria;
private JTextArea txtSQL;
public SearchManager() throws Exception {
super("Builder Pattern - Example");
// Create controls
cmbSearchType = new JComboBox();
txtSQL = new JTextArea(" The SQL statement will be displayed here.", 5,
25);
txtSQL.setFont(new Font("Serif", Font.ITALIC, 12));
txtSQL.setLineWrap(true);
txtSQL.setWrapStyleWord(true);
pSearchCriteria = new JPanel();
cmbSearchType.addItem(SearchManager.BLANK);
cmbSearchType.addItem(SearchManager.CANDIDATE_SRCH);
cmbSearchType.addItem(SearchManager.EMPLOYER_SRCH);
//Create Labels
JLabel lblSearchType = new JLabel("Search:");
JLabel lblWhereClause = new JLabel("SQL:");
JLabel lblSearchCriteria = new JLabel("Search Criteria:");
//Create the open button
JButton btnGetWhereClause = new JButton(SearchManager.GET_SQL);
btnGetWhereClause.setMnemonic(KeyEvent.VK_G);
JButton btnExit = new JButton(SearchManager.EXIT);
btnExit.setMnemonic(KeyEvent.VK_X);
buttonHandler vf = new buttonHandler(this);
btnGetWhereClause.addActionListener(vf);
btnExit.addActionListener(vf);
cmbSearchType.addActionListener(vf);
//For layout purposes, put the buttons in a separate panel
JPanel buttonPanel = new JPanel();
//****************************************************
GridBagLayout gridbag = new GridBagLayout();
buttonPanel.setLayout(gridbag);
GridBagConstraints gbc = new GridBagConstraints();
buttonPanel.add(lblSearchType);
buttonPanel.add(cmbSearchType);
buttonPanel.add(lblSearchCriteria);
buttonPanel.add(pSearchCriteria);
buttonPanel.add(lblWhereClause);
buttonPanel.add(txtSQL);
buttonPanel.add(btnGetWhereClause);
buttonPanel.add(btnExit);
gbc.insets.top = 5;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 0;
gbc.gridy = 0;
gridbag.setConstraints(lblSearchType, gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gridbag.setConstraints(cmbSearchType, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gridbag.setConstraints(lblSearchCriteria, gbc);
gbc.gridx = 1;
gbc.gridy = 2;
gridbag.setConstraints(pSearchCriteria, gbc);
gbc.gridx = 0;
gbc.gridy = 3;
gridbag.setConstraints(lblWhereClause, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridwidth = 3;
gbc.gridheight = 5;
gbc.gridx = 1;
gbc.gridy = 3;
gridbag.setConstraints(txtSQL, gbc);
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.anchor = GridBagConstraints.EAST;
gbc.insets.left = 2;
gbc.insets.right = 2;
gbc.insets.top = 40;
gbc.gridx = 0;
gbc.gridy = 8;
gridbag.setConstraints(btnGetWhereClause, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 1;
gbc.gridy = 8;
gridbag.setConstraints(btnExit, gbc);
//****************************************************
//Add the buttons and the log to the frame
Container contentPane = getContentPane();
contentPane.add(buttonPanel, BorderLayout.CENTER);
try {
UIManager.setLookAndFeel(new WindowsLookAndFeel());
SwingUtilities.updateComponentTreeUI(SearchManager.this);
} catch (Exception ex) {
System.out.println(ex);
}
}
public void setSQL(String str) {
txtSQL.setText(str);
}
public String getSearchType() {
return (String) cmbSearchType.getSelectedItem();
}
public JComboBox getSearchTypeCtrl() {
return cmbSearchType;
}
public void displayNewUI(JPanel panel) {
pSearchCriteria.removeAll();
pSearchCriteria.add(panel);
pSearchCriteria.validate();
validate();
}
public static void main(String[] args) throws Exception {
JFrame frame = new SearchManager();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//frame.pack();
frame.setSize(450, 400);
frame.setVisible(true);
}
}
class buttonHandler implements ActionListener {
SearchManager manager;
UIBuilder builder;
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals(SearchManager.EXIT)) {
System.exit(1);
}
if (e.getActionCommand().equals(SearchManager.GET_SQL)) {
manager.setSQL(builder.getSQL());
}
if (e.getSource() == manager.getSearchTypeCtrl()) {
String selection = manager.getSearchType();
if (selection.equals("") == false) {
BuilderFactory factory = new BuilderFactory();
//create an appropriate builder instance
builder = factory.getUIBuilder(selection);
//configure the director with the builder
UIDirector director = new UIDirector(builder);
//director invokes different builder
// methods
director.build();
//get the final build object
JPanel UIObj = builder.getSearchUI();
manager.displayNewUI(UIObj);
}
}
}
public buttonHandler() {
}
public buttonHandler(SearchManager inManager) {
manager = inManager;
}
}
class MyUtil {
public static String handleRecordLength(String str, int len) {
int i;
String retStr = "";
if (str.length() > len) {
retStr = str.substring(0, len);
} else {
i = len - str.length();
for (int j = 0; j < i; j++) {
str = str + " ";
}
retStr = str;
}
return retStr;
}
}
class BuilderFactory {
public UIBuilder getUIBuilder(String str) {
UIBuilder builder = null;
if (str.equals(SearchManager.CANDIDATE_SRCH)) {
builder = new CandSrchBuilder();
} else if (str.equals(SearchManager.EMPLOYER_SRCH)) {
builder = new EmpSrchBuilder();
}
return builder;
}
}
abstract class UIBuilder {
protected JPanel searchUI;
public abstract void addUIControls();
public abstract void initialize();
public abstract String getSQL();
public JPanel getSearchUI() {
return searchUI;
}
}
class UIDirector {
private UIBuilder builder;
public UIDirector(UIBuilder bldr) {
builder = bldr;
}
public void build() {
builder.addUIControls();
builder.initialize();
}
}
class EmpSrchBuilder extends UIBuilder {
JLabel lblUserName = new JLabel("Name :");
private JTextField txtUserName = new JTextField(15);
private JTextField txtCity = new JTextField(15);
private JTextField txtRenewal = new JTextField(10);
public void addUIControls() {
searchUI = new JPanel();
JLabel lblUserName = new JLabel("Name :");
JLabel lblCity = new JLabel("City:");
JLabel lblRenewal = new JLabel("Membership Renewal :");
GridBagLayout gridbag = new GridBagLayout();
searchUI.setLayout(gridbag);
GridBagConstraints gbc = new GridBagConstraints();
searchUI.add(lblUserName);
searchUI.add(txtUserName);
searchUI.add(lblCity);
searchUI.add(txtCity);
searchUI.add(lblRenewal);
searchUI.add(txtRenewal);
gbc.anchor = GridBagConstraints.WEST;
gbc.insets.top = 5;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.gridx = 0;
gbc.gridy = 0;
gridbag.setConstraints(lblUserName, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gridbag.setConstraints(lblCity, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gridbag.setConstraints(lblRenewal, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 1;
gbc.gridy = 0;
gridbag.setConstraints(txtUserName, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gridbag.setConstraints(txtCity, gbc);
gbc.gridx = 1;
gbc.gridy = 2;
gridbag.setConstraints(txtRenewal, gbc);
}
public void initialize() {
Calendar cal = Calendar.getInstance();
cal.setTime(new java.util.Date());
txtUserName.setText("Enter UserName Here");
txtRenewal.setText((cal.get(Calendar.MONTH) + 1) + "/"
+ cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR));
}
public String getSQL() {
return ("Select * from Employer where Username=""
+ txtUserName.getText() + """ + " and City=""
+ txtCity.getText() + "" and DateRenewal=""
+ txtRenewal.getText() + """);
}
}
class CandSrchBuilder extends UIBuilder {
private JTextField txtUserName = new JTextField(15);
private JTextField txtSkill = new JTextField(10);
private JComboBox cmbExperience = new JComboBox();
public void addUIControls() {
searchUI = new JPanel();
JLabel lblUserName = new JLabel("Name :");
JLabel lblExperienceRange = new JLabel("Experience(min Yrs.):");
JLabel lblSkill = new JLabel("Skill :");
cmbExperience.addItem("<5");
cmbExperience.addItem(">5");
GridBagLayout gridbag = new GridBagLayout();
searchUI.setLayout(gridbag);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.WEST;
searchUI.add(lblUserName);
searchUI.add(txtUserName);
searchUI.add(lblExperienceRange);
searchUI.add(cmbExperience);
searchUI.add(lblSkill);
searchUI.add(txtSkill);
gbc.insets.top = 5;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.gridx = 0;
gbc.gridy = 0;
gridbag.setConstraints(lblUserName, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gridbag.setConstraints(lblExperienceRange, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
gridbag.setConstraints(lblSkill, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 1;
gbc.gridy = 0;
gridbag.setConstraints(txtUserName, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gridbag.setConstraints(cmbExperience, gbc);
gbc.gridx = 1;
gbc.gridy = 2;
gridbag.setConstraints(txtSkill, gbc);
}
public void initialize() {
txtUserName.setText("Enter UserName Here");
txtSkill.setText("Internet Tech");
}
public String getSQL() {
String experience = (String) cmbExperience.getSelectedItem();
return ("Select * from Candidate where Username=""
+ txtUserName.getText() + "" and Experience " + experience
+ " and Skill="" + txtSkill.getText() + """);
}
}
Builder Pattern in Java
//[C] 2002 Sun Microsystems, Inc.---
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
public class RunBuilderPattern {
private static Calendar dateCreator = Calendar.getInstance();
public static void main(String [] arguments){
Appointment appt = null;
System.out.println("Example for the Builder pattern");
System.out.println();
System.out.println("This example demonstrates the use of the Builder");
System.out.println("pattern to create Appointment objects for the PIM.");
System.out.println();
System.out.println("Creating a Scheduler for the example.");
Scheduler pimScheduler = new Scheduler();
System.out.println("Creating an AppointmentBuilder for the example.");
System.out.println();
AppointmentBuilder apptBuilder = new AppointmentBuilder();
try{
System.out.println("Creating a new Appointment with an AppointmentBuilder");
appt = pimScheduler.createAppointment(
apptBuilder, createDate(2066, 9, 22, 12, 30),
null, "Trek convention", new LocationImpl("Fargo, ND"),
createAttendees(4));
System.out.println("Successfully created an Appointment.");
System.out.println("Appointment information:");
System.out.println(appt);
System.out.println();
}
catch (InformationRequiredException exc){
printExceptions(exc);
}
System.out.println("Creating a MeetingBuilder for the example.");
MeetingBuilder mtgBuilder = new MeetingBuilder();
try{
System.out.println("Creating a new Appointment with a MeetingBuilder");
System.out.println("(notice that the same create arguments will produce");
System.out.println(" an exception, since the MeetingBuilder enforces a");
System.out.println(" mandatory end date)");
appt = pimScheduler.createAppointment(
mtgBuilder, createDate(2066, 9, 22, 12, 30),
null, "Trek convention", new LocationImpl("Fargo, ND"),
createAttendees(4));
System.out.println("Successfully created an Appointment.");
System.out.println("Appointment information:");
System.out.println(appt);
System.out.println();
}
catch (InformationRequiredException exc){
printExceptions(exc);
}
System.out.println("Creating a new Appointment with a MeetingBuilder");
System.out.println("(This time, the MeetingBuilder will provide an end date)");
try{
appt = pimScheduler.createAppointment(
mtgBuilder,
createDate(2002, 4, 1, 10, 00),
createDate(2002, 4, 1, 11, 30),
"OOO Meeting",
new LocationImpl("Butte, MT"),
createAttendees(2));
System.out.println("Successfully created an Appointment.");
System.out.println("Appointment information:");
System.out.println(appt);
System.out.println();
}
catch (InformationRequiredException exc){
printExceptions(exc);
}
}
public static Date createDate(int year, int month, int day, int hour, int minute){
dateCreator.set(year, month, day, hour, minute);
return dateCreator.getTime();
}
public static ArrayList createAttendees(int numberToCreate){
ArrayList group = new ArrayList();
for (int i = 0; i < numberToCreate; i++){
group.add(new ContactImpl("John", getLastName(i), "Employee (non-exempt)", "Yoyodyne Corporation"));
}
return group;
}
public static String getLastName(int index){
String name = "";
switch (index % 6){
case 0: name = "Worfin";
break;
case 1: name = "Smallberries";
break;
case 2: name = "Bigbootee";
break;
case 3: name = "Haugland";
break;
case 4: name = "Maassen";
break;
case 5: name = "Sterling";
break;
}
return name;
}
public static void printExceptions(InformationRequiredException exc){
int statusCode = exc.getInformationRequired();
System.out.println("Unable to create Appointment: additional information is required");
if ((statusCode & InformationRequiredException.START_DATE_REQUIRED) > 0){
System.out.println(" A start date is required for this appointment to be complete.");
}
if ((statusCode & InformationRequiredException.END_DATE_REQUIRED) > 0){
System.out.println(" An end date is required for this appointment to be complete.");
}
if ((statusCode & InformationRequiredException.DESCRIPTION_REQUIRED) > 0){
System.out.println(" A description is required for this appointment to be complete.");
}
if ((statusCode & InformationRequiredException.ATTENDEE_REQUIRED) > 0){
System.out.println(" At least one attendee is required for this appointment to be complete.");
}
if ((statusCode & InformationRequiredException.LOCATION_REQUIRED) > 0){
System.out.println(" A location is required for this appointment to be complete.");
}
System.out.println();
}
}
interface Contact extends Serializable{
public static final String SPACE = " ";
public String getFirstName();
public String getLastName();
public String getTitle();
public String getOrganization();
public void setFirstName(String newFirstName);
public void setLastName(String newLastName);
public void setTitle(String newTitle);
public void setOrganization(String newOrganization);
}
class ContactImpl implements Contact{
private String firstName;
private String lastName;
private String title;
private String organization;
public ContactImpl(String newFirstName, String newLastName,
String newTitle, String newOrganization){
firstName = newFirstName;
lastName = newLastName;
title = newTitle;
organization = newOrganization;
}
public String getFirstName(){ return firstName; }
public String getLastName(){ return lastName; }
public String getTitle(){ return title; }
public String getOrganization(){ return organization; }
public void setFirstName(String newFirstName){ firstName = newFirstName; }
public void setLastName(String newLastName){ lastName = newLastName; }
public void setTitle(String newTitle){ title = newTitle; }
public void setOrganization(String newOrganization){ organization = newOrganization; }
public String toString(){
return firstName + SPACE + lastName;
}
}
interface Location extends Serializable{
public String getLocation();
public void setLocation(String newLocation);
}
class LocationImpl implements Location{
private String location;
public LocationImpl(){ }
public LocationImpl(String newLocation){
location = newLocation;
}
public String getLocation(){ return location; }
public void setLocation(String newLocation){ location = newLocation; }
public String toString(){ return location; }
}
class Scheduler{
public Appointment createAppointment(AppointmentBuilder builder,
Date startDate, Date endDate, String description,
Location location, ArrayList attendees) throws InformationRequiredException{
if (builder == null){
builder = new AppointmentBuilder();
}
builder.buildAppointment();
builder.buildDates(startDate, endDate);
builder.buildDescription(description);
builder.buildAttendees(attendees);
builder.buildLocation(location);
return builder.getAppointment();
}
}
class Appointment{
private Date startDate;
private Date endDate;
private String description;
private ArrayList attendees = new ArrayList();
private Location location;
public static final String EOL_STRING =
System.getProperty("line.separator");
public Date getStartDate(){ return startDate; }
public Date getEndDate(){ return endDate; }
public String getDescription(){ return description; }
public ArrayList getAttendees(){ return attendees; }
public Location getLocation(){ return location; }
public void setDescription(String newDescription){ description = newDescription; }
public void setLocation(Location newLocation){ location = newLocation; }
public void setStartDate(Date newStartDate){ startDate = newStartDate; }
public void setEndDate(Date newEndDate){ endDate = newEndDate; }
public void setAttendees(ArrayList newAttendees){
if (newAttendees != null){
attendees = newAttendees;
}
}
public void addAttendee(Contact attendee){
if (!attendees.contains(attendee)){
attendees.add(attendee);
}
}
public void removeAttendee(Contact attendee){
attendees.remove(attendee);
}
public String toString(){
return " Description: " + description + EOL_STRING +
" Start Date: " + startDate + EOL_STRING +
" End Date: " + endDate + EOL_STRING +
" Location: " + location + EOL_STRING +
" Attendees: " + attendees;
}
}
class AppointmentBuilder{
public static final int START_DATE_REQUIRED = 1;
public static final int END_DATE_REQUIRED = 2;
public static final int DESCRIPTION_REQUIRED = 4;
public static final int ATTENDEE_REQUIRED = 8;
public static final int LOCATION_REQUIRED = 16;
protected Appointment appointment;
protected int requiredElements;
public void buildAppointment(){
appointment = new Appointment();
}
public void buildDates(Date startDate, Date endDate){
Date currentDate = new Date();
if ((startDate != null) && (startDate.after(currentDate))){
appointment.setStartDate(startDate);
}
if ((endDate != null) && (endDate.after(startDate))){
appointment.setEndDate(endDate);
}
}
public void buildDescription(String newDescription){
appointment.setDescription(newDescription);
}
public void buildAttendees(ArrayList attendees){
if ((attendees != null) && (!attendees.isEmpty())){
appointment.setAttendees(attendees);
}
}
public void buildLocation(Location newLocation){
if (newLocation != null){
appointment.setLocation(newLocation);
}
}
public Appointment getAppointment() throws InformationRequiredException{
requiredElements = 0;
if (appointment.getStartDate() == null){
requiredElements += START_DATE_REQUIRED;
}
if (appointment.getLocation() == null){
requiredElements += LOCATION_REQUIRED;
}
if (appointment.getAttendees().isEmpty()){
requiredElements += ATTENDEE_REQUIRED;
}
if (requiredElements > 0){
throw new InformationRequiredException(requiredElements);
}
return appointment;
}
public int getRequiredElements(){ return requiredElements; }
}
class InformationRequiredException extends Exception{
private static final String MESSAGE = "Appointment cannot be created because further information is required";
public static final int START_DATE_REQUIRED = 1;
public static final int END_DATE_REQUIRED = 2;
public static final int DESCRIPTION_REQUIRED = 4;
public static final int ATTENDEE_REQUIRED = 8;
public static final int LOCATION_REQUIRED = 16;
private int informationRequired;
public InformationRequiredException(int itemsRequired){
super(MESSAGE);
informationRequired = itemsRequired;
}
public int getInformationRequired(){ return informationRequired; }
}
class MeetingBuilder extends AppointmentBuilder{
public Appointment getAppointment() throws InformationRequiredException{
try{
super.getAppointment();
}
finally{
if (appointment.getEndDate() == null){
requiredElements += END_DATE_REQUIRED;
}
if (requiredElements > 0){
throw new InformationRequiredException(requiredElements);
}
}
return appointment;
}
}