This hands-on lab takes you through the basic Java patterns.
Expected duration: 120 minutes
Before you begin, you need to install the following software on your
computer.
| public class SingletonPattern { public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); System.out.println("Calling a method of a Singleton: " + s1.demoMethod()); Singleton s2 = Singleton.getInstance(); System.out.println("Calling a method of a Singleton: " + s2.demoMethod()); boolean b1 = (s1 == s2); System.out.println("Object instance s1 and s2 are the same object: " + b1); } } |
| public
class Singleton { private static Singleton singleton = new Singleton(); /** A private Constructor prevents any other class from instantiating. */ private Singleton() { } /** Static 'instance' method */ public static Singleton getInstance() { return singleton; } // other methods protected by singleton-ness would be here... /** A simple demo method */ public String demoMethod() { return "demo"; } } |
| Calling a method of a Singleton:
demo Calling a method of a Singleton: demo Object instance s1 and s2 are the same object: true |
In this exercise, you are going to learn
how to write a Java program using FactoryMethod pattern.
| public class
FactoryMethodPattern { public static void main(String [] arguments){ System.out.println("Example for the FactoryMethod pattern - Creating a GUI editor for the Contact\n"); System.out.println("The GUI defined in the EditorGui class is a truly generic editor."); System.out.println("It accepts an argument of type ItemEditor, and delegates"); System.out.println(" all editing tasks to its ItemEditorInterface and the associated GUI."); System.out.println(" The getEditor() Factory Method is used to obtain the ItemEditor"); System.out.println(" for the example."); System.out.println(); System.out.println("Notice that the editor in the top portion of the GUI is,"); System.out.println(" in fact, returned by the ItemEditor belonging to the"); System.out.println(" ContactEditableImpl class, and has appropriate fields for that class.\n"); // Create ContactEditableImpl object System.out.println("Creating a Contact object.\n"); ContactEditableImpl someone = new ContactEditableImpl(); EditorGui editorGui = new EditorGui(someone.getEditor()); editorGui.createGui(); } } |
| import java.awt.GridLayout; import java.io.Serializable; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; class ContactEditableImpl implements EditableInterface, Serializable { private String name; private String relationship; // Factory method public ItemEditorInterface getEditor() { return new ContactEditorItemEditorImpl(); } private class ContactEditorItemEditorImpl implements ItemEditorInterface, Serializable { private transient JPanel panel; private transient JTextField nameField; private transient JTextField relationField; public JComponent getGUI() { if (panel == null) { panel = new JPanel(); nameField = new JTextField(name); relationField = new JTextField(relationship); panel.setLayout(new GridLayout(2,2)); panel.add(new JLabel("Name:")); panel.add(nameField); panel.add(new JLabel("Relationship:")); panel.add(relationField); } else { nameField.setText(name); relationField.setText(relationship); } return panel; } public void commitChanges() { if (panel != null) { name = nameField.getText(); relationship = relationField.getText(); } } public String toString(){ return "\nContact:\n" + " Name: " + name + "\n" + " Relationship: " + relationship; } } } |
| interface
EditableInterface { public ItemEditorInterface getEditor(); } |
| import
javax.swing.JComponent; interface ItemEditorInterface { public JComponent getGUI(); public void commitChanges(); } |
| import
java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextArea; class EditorGui implements ActionListener{ private JFrame mainFrame; private JTextArea display; private JButton update, exit; private JPanel controlPanel, displayPanel, editorPanel; // ItemEditorInterface field private ItemEditorInterface editor; public EditorGui(ItemEditorInterface edit){ editor = edit; } public void createGui(){ mainFrame = new JFrame("Factory Pattern Example"); Container content = mainFrame.getContentPane(); content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); editorPanel = new JPanel(); editorPanel.add(editor.getGUI()); content.add(editorPanel); displayPanel = new JPanel(); display = new JTextArea(10, 40); display.setEditable(false); displayPanel.add(display); content.add(displayPanel); controlPanel = new JPanel(); update = new JButton("Update Item"); exit = new JButton("Exit"); controlPanel.add(update); controlPanel.add(exit); content.add(controlPanel); update.addActionListener(this); exit.addActionListener(this); mainFrame.addWindowListener(new WindowCloseManager()); mainFrame.pack(); mainFrame.setVisible(true); } public void actionPerformed(ActionEvent evt){ Object originator = evt.getSource(); if (originator == update){ updateItem(); } else if (originator == exit){ exitApplication(); } } private class WindowCloseManager extends WindowAdapter{ public void windowClosing(WindowEvent evt){ exitApplication(); } } private void updateItem(){ editor.commitChanges(); display.setText(editor.toString()); } private void exitApplication(){ System.exit(0); } } |
| Example for the FactoryMethod
pattern - Creating a GUI editor for the Contact The GUI defined in the EditorGui class is a truly generic editor. It accepts an argument of type ItemEditor, and delegates all editing tasks to its ItemEditorInterface and the associated GUI. The getEditor() Factory Method is used to obtain the ItemEditor for the example. Notice that the editor in the top portion of the GUI is, in fact, returned by the ItemEditor belonging to the ContactEditableImpl class, and has appropriate fields for that class. Creating a Contact object. |
In this exercise, you have learned
about FactoryMethod pattern.
| public class
AbstractFactoryPattern { public static void main(String [] arguments){ System.out.println("Example for the AbstractFactory pattern"); System.out.println(); System.out.println(" Notice that you can"); System.out.println(" use the Address and PhoneNumber classes when writing"); System.out.println(" almost all of the code. This allows you to write a very"); System.out.println(" generic framework, and plug in Concrete Factories"); System.out.println(" and Products to specialize the behavior of your code)"); System.out.println(); System.out.println("Creating U.S. Address and Phone Number:"); AddressFactoryInterface addressFactory = new USAddressFactoryImpl(); AddressAbstractClass address = addressFactory.createAddress(); PhoneNumberAbstractClass phone = addressFactory.createPhoneNumber(); address.setStreet("142 Lois Lane"); address.setCity("Metropolis"); address.setRegion("WY"); address.setPostalCode("54321"); phone.setPhoneNumber("7039214722"); System.out.println("U.S. address:"); System.out.println(address.getFullAddress()); System.out.println("U.S. phone number:"); System.out.println(phone.getPhoneNumber()); System.out.println(); System.out.println(); System.out.println("Creating French Address and Phone Number:"); addressFactory = new FrenchAddressFactoryImpl(); address = addressFactory.createAddress(); phone = addressFactory.createPhoneNumber(); address.setStreet("21 Rue Victor Hugo"); address.setCity("Courbevoie"); address.setPostalCode("40792"); phone.setPhoneNumber("011324290"); System.out.println("French address:"); System.out.println(address.getFullAddress()); System.out.println("French phone number:"); System.out.println(phone.getPhoneNumber()); } } |
| interface
AddressFactoryInterface { public AddressAbstractClass createAddress(); public PhoneNumberAbstractClass createPhoneNumber(); } |
| class
USAddressFactoryImpl implements AddressFactoryInterface{ public AddressAbstractClass createAddress(){ return new USAddress(); } public PhoneNumberAbstractClass createPhoneNumber(){ return new USPhoneNumber(); } } |
| class
FrenchAddressFactoryImpl implements AddressFactoryInterface { public AddressAbstractClass createAddress(){ return new FrenchAddress(); } public PhoneNumberAbstractClass createPhoneNumber(){ return new FrenchPhoneNumber(); } } |
| abstract
class AddressAbstractClass{ private String street; private String city; private String region; private String postalCode; public static final String EOL_STRING = System.getProperty("line.separator"); public static final String SPACE = " "; public String getStreet(){ return street; } public String getCity(){ return city; } public String getPostalCode(){ return postalCode; } public String getRegion(){ return region; } // Abstract method public abstract String getCountry(); public String getFullAddress(){ return street + EOL_STRING + city + SPACE + postalCode + EOL_STRING; } public void setStreet(String newStreet){ street = newStreet; } public void setCity(String newCity){ city = newCity; } public void setRegion(String newRegion){ region = newRegion; } public void setPostalCode(String newPostalCode){ postalCode = newPostalCode; } } |
| abstract
class PhoneNumberAbstractClass{ private String phoneNumber; // Abstract method public abstract String getCountryCode(); public String getPhoneNumber(){ return phoneNumber; } public void setPhoneNumber(String newNumber){ try{ Long.parseLong(newNumber); phoneNumber = newNumber; } catch (NumberFormatException exc){ } } } |
| class
USAddress extends AddressAbstractClass{ private static final String COUNTRY = "UNITED STATES"; private static final String COMMA = ","; // Concrete method public String getCountry(){ return COUNTRY; } public String getFullAddress(){ return getStreet() + EOL_STRING + getCity() + COMMA + SPACE + getRegion() + SPACE + getPostalCode() + EOL_STRING + COUNTRY + EOL_STRING; } } |
| class
FrenchAddress extends AddressAbstractClass { private static final String COUNTRY = "FRANCE"; // Concrete method public String getCountry(){ return COUNTRY; } public String getFullAddress(){ return getStreet() + EOL_STRING + getPostalCode() + SPACE + getCity() + EOL_STRING + COUNTRY + EOL_STRING; } } |
| class
USPhoneNumber extends PhoneNumberAbstractClass{ private static final String COUNTRY_CODE = "01"; private static final int NUMBER_LENGTH = 10; // Concrete method public String getCountryCode(){ return COUNTRY_CODE; } public void setPhoneNumber(String newNumber){ if (newNumber.length() == NUMBER_LENGTH){ super.setPhoneNumber(newNumber); } } } |
| class
FrenchPhoneNumber extends PhoneNumberAbstractClass{ private static final String COUNTRY_CODE = "33"; private static final int NUMBER_LENGTH = 9; // Concrete method public String getCountryCode(){ return COUNTRY_CODE; } public void setPhoneNumber(String newNumber){ if (newNumber.length() == NUMBER_LENGTH){ super.setPhoneNumber(newNumber); } } } |
| Example for the AbstractFactory
pattern Notice that you can use the Address and PhoneNumber classes when writing almost all of the code. This allows you to write a very generic framework, and plug in Concrete Factories and Products to specialize the behavior of your code) Creating U.S. Address and Phone Number: U.S. address: 142 Lois Lane Metropolis, WY 54321 UNITED STATES U.S. phone number: 7039214722 Creating French Address and Phone Number: French address: 21 Rue Victor Hugo 40792 Courbevoie FRANCE French phone number: 011324290 |