Java/Design Pattern/Factory Pattern
Содержание
Abstract Factory Pattern- Example
<source lang="java">
/* Software Architecture Design Patterns in Java by Partha Kuchana Auerbach Publications
- /
import java.awt.BorderLayout; import java.awt.Container; 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 javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import com.sun.java.swing.plaf.windows.WindowsLookAndFeel; public class AutoSearchUI extends JFrame {
public static final String newline = "\n"; public static final String SEARCH = "Search"; public static final String EXIT = "Exit"; public static final String CAR = "Car"; public static final String SUV = "SUV"; private JComboBox cmbVehicleCategory, cmbVehicleType; private JLabel lblVehicleCategory, lblVehicleType, lblCarName, lblCarNameValue; public AutoSearchUI() { super("Abstract Factory - Example"); cmbVehicleCategory = new JComboBox(); cmbVehicleCategory.addItem(VehicleFactory.LUXURY_VEHICLE); cmbVehicleCategory.addItem(VehicleFactory.NON_LUXURY_VEHICLE); cmbVehicleType = new JComboBox(); cmbVehicleType.addItem(AutoSearchUI.CAR); cmbVehicleType.addItem(AutoSearchUI.SUV); lblVehicleCategory = new JLabel("Vehicle Category:"); lblVehicleType = new JLabel("VehicleType:"); lblCarName = new JLabel("Search Result:"); lblCarNameValue = new JLabel(" Please click on Search button"); //Create the open button JButton openButton = new JButton(AutoSearchUI.SEARCH); openButton.setMnemonic(KeyEvent.VK_S); JButton exitButton = new JButton(AutoSearchUI.EXIT); exitButton.setMnemonic(KeyEvent.VK_X); ButtonHandler objButtonHandler = new ButtonHandler(this); openButton.addActionListener(objButtonHandler); exitButton.addActionListener(new ButtonHandler()); JPanel buttonPanel = new JPanel(); //**************************************************** GridBagLayout gridbag = new GridBagLayout(); buttonPanel.setLayout(gridbag); GridBagConstraints gbc = new GridBagConstraints(); buttonPanel.add(lblVehicleCategory); buttonPanel.add(cmbVehicleCategory); buttonPanel.add(lblVehicleType); buttonPanel.add(cmbVehicleType); buttonPanel.add(lblCarName); buttonPanel.add(lblCarNameValue); buttonPanel.add(openButton); buttonPanel.add(exitButton); gbc.insets.top = 5; gbc.insets.bottom = 5; gbc.insets.left = 5; gbc.insets.right = 5; gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 0; gridbag.setConstraints(lblVehicleCategory, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 0; gridbag.setConstraints(cmbVehicleCategory, gbc); gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 1; gridbag.setConstraints(lblVehicleType, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 1; gridbag.setConstraints(cmbVehicleType, gbc); gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 2; gridbag.setConstraints(lblCarName, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 2; gridbag.setConstraints(lblCarNameValue, gbc); gbc.insets.left = 2; gbc.insets.right = 2; gbc.insets.top = 40; gbc.anchor = GridBagConstraints.EAST; gbc.gridx = 0; gbc.gridy = 5; gridbag.setConstraints(openButton, gbc); gbc.anchor = GridBagConstraints.WEST; gbc.gridx = 1; gbc.gridy = 5; gridbag.setConstraints(exitButton, 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(AutoSearchUI.this); } catch (Exception ex) { System.out.println(ex); } } public static void main(String[] args) { JFrame frame = new AutoSearchUI(); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); //frame.pack(); frame.setSize(400, 300); frame.setVisible(true); } public String getSelectedCategory() { return (String) cmbVehicleCategory.getSelectedItem(); } public String getSelectedType() { return (String) cmbVehicleType.getSelectedItem(); } public void setResult(String searchResult) { lblCarNameValue.setText(searchResult); }
} // End of class AutoSearchUI class ButtonHandler implements ActionListener {
AutoSearchUI objAutoSearchUI; public void actionPerformed(ActionEvent e) { String searchResult = null; if (e.getActionCommand().equals(AutoSearchUI.EXIT)) { System.exit(1); } if (e.getActionCommand().equals(AutoSearchUI.SEARCH)) { //get input values String vhCategory = objAutoSearchUI.getSelectedCategory(); String vhType = objAutoSearchUI.getSelectedType(); //get one of Luxury or NonLuxury vehicle factories VehicleFactory vf = VehicleFactory.getVehicleFactory(vhCategory); if (vhType.equals(AutoSearchUI.CAR)) { Car c = vf.getCar(); searchResult = "Name: " + c.getCarName() + " Features: " + c.getCarFeatures(); } if (vhType.equals(AutoSearchUI.SUV)) { SUV s = vf.getSUV(); searchResult = "Name: " + s.getSUVName() + " Features: " + s.getSUVFeatures(); } objAutoSearchUI.setResult(searchResult); } } public ButtonHandler() { } public ButtonHandler(AutoSearchUI inObjAutoSearchUI) { objAutoSearchUI = inObjAutoSearchUI; }
} // End of class ButtonHandler abstract class VehicleFactory {
public static final String LUXURY_VEHICLE = "Luxury"; public static final String NON_LUXURY_VEHICLE = "Non-Luxury"; public abstract Car getCar(); public abstract SUV getSUV(); public static VehicleFactory getVehicleFactory(String type) { if (type.equals(VehicleFactory.LUXURY_VEHICLE)) return new LuxuryVehicleFactory(); if (type.equals(VehicleFactory.NON_LUXURY_VEHICLE)) return new NonLuxuryVehicleFactory(); return new LuxuryVehicleFactory(); }
} // End of class interface Car {
public String getCarName(); public String getCarFeatures();
} // End of class interface SUV {
public String getSUVName(); public String getSUVFeatures();
} // End of class class LuxuryCar implements Car {
private String name; public LuxuryCar(String cName) { name = cName; } public String getCarName() { return name; } public String getCarFeatures() { return "Luxury Car Features "; };
} // End of class class LuxurySUV implements SUV {
private String name; public LuxurySUV(String sName) { name = sName; } public String getSUVName() { return name; } public String getSUVFeatures() { return "Luxury SUV Features "; };
} // End of class class LuxuryVehicleFactory extends VehicleFactory {
public Car getCar() { return new LuxuryCar("L-C"); } public SUV getSUV() { return new LuxurySUV("L-S"); }
} // End of class class NonLuxuryCar implements Car {
private String name; public NonLuxuryCar(String cName) { name = cName; } public String getCarName() { return name; } public String getCarFeatures() { return "Non-Luxury Car Features "; };
} // End of class class NonLuxurySUV implements SUV {
private String name; public NonLuxurySUV(String sName) { name = sName; } public String getSUVName() { return name; } public String getSUVFeatures() { return "Non-Luxury SUV Features "; };
} // End of class class NonLuxuryVehicleFactory extends VehicleFactory {
public Car getCar() { return new NonLuxuryCar("NL-C"); } public SUV getSUV() { return new NonLuxurySUV("NL-S"); }
} // End of class
</source>
Abstract Factory Pattern in Java 2
<source lang="java">
//[C] 2002 Sun Microsystems, Inc.--- public class RunAbstractFactoryPattern {
public static void main(String [] arguments){ System.out.println("Example for the AbstractFactory pattern"); System.out.println(); System.out.println(" (take a look in the RunPattern code. 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:"); AddressFactory usAddressFactory = new USAddressFactory(); Address usAddress = usAddressFactory.createAddress(); PhoneNumber usPhone = usAddressFactory.createPhoneNumber(); usAddress.setStreet("142 Lois Lane"); usAddress.setCity("Metropolis"); usAddress.setRegion("WY"); usAddress.setPostalCode("54321"); usPhone.setPhoneNumber("7039214722"); System.out.println("U.S. address:"); System.out.println(usAddress.getFullAddress()); System.out.println("U.S. phone number:"); System.out.println(usPhone.getPhoneNumber()); System.out.println(); System.out.println(); System.out.println("Creating French Address and Phone Number:"); AddressFactory frenchAddressFactory = new FrenchAddressFactory(); Address frenchAddress = frenchAddressFactory.createAddress(); PhoneNumber frenchPhone = frenchAddressFactory.createPhoneNumber(); frenchAddress.setStreet("21 Rue Victor Hugo"); frenchAddress.setCity("Courbevoie"); frenchAddress.setPostalCode("40792"); frenchPhone.setPhoneNumber("011324290"); System.out.println("French address:"); System.out.println(frenchAddress.getFullAddress()); System.out.println("French phone number:"); System.out.println(frenchPhone.getPhoneNumber()); }
} class FrenchAddressFactory implements AddressFactory{
public Address createAddress(){ return new FrenchAddress(); } public PhoneNumber createPhoneNumber(){ return new FrenchPhoneNumber(); }
} class USAddressFactory implements AddressFactory{
public Address createAddress(){ return new USAddress(); } public PhoneNumber createPhoneNumber(){ return new USPhoneNumber(); }
} class USPhoneNumber extends PhoneNumber{
private static final String COUNTRY_CODE = "01"; private static final int NUMBER_LENGTH = 10; public String getCountryCode(){ return COUNTRY_CODE; } public void setPhoneNumber(String newNumber){ if (newNumber.length() == NUMBER_LENGTH){ super.setPhoneNumber(newNumber); } }
} interface AddressFactory{
public Address createAddress(); public PhoneNumber createPhoneNumber();
} abstract class Address{
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; } 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 PhoneNumber{
private String phoneNumber; public abstract String getCountryCode(); public String getPhoneNumber(){ return phoneNumber; } public void setPhoneNumber(String newNumber){ try{ Long.parseLong(newNumber); phoneNumber = newNumber; } catch (NumberFormatException exc){ } }
}
class FrenchPhoneNumber extends PhoneNumber{
private static final String COUNTRY_CODE = "33"; private static final int NUMBER_LENGTH = 9; public String getCountryCode(){ return COUNTRY_CODE; } public void setPhoneNumber(String newNumber){ if (newNumber.length() == NUMBER_LENGTH){ super.setPhoneNumber(newNumber); } }
} class FrenchAddress extends Address{
private static final String COUNTRY = "FRANCE"; public String getCountry(){ return COUNTRY; } public String getFullAddress(){ return getStreet() + EOL_STRING + getPostalCode() + SPACE + getCity() + EOL_STRING + COUNTRY + EOL_STRING; }
} class USAddress extends Address{
private static final String COUNTRY = "UNITED STATES"; private static final String COMMA = ","; public String getCountry(){ return COUNTRY; } public String getFullAddress(){ return getStreet() + EOL_STRING + getCity() + COMMA + SPACE + getRegion() + SPACE + getPostalCode() + EOL_STRING + COUNTRY + EOL_STRING; }
}
</source>
Factory Method Pattern in Java
<source lang="java">
//[C] 2002 Sun Microsystems, Inc.--- import java.awt.Container; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.Serializable; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField;
public class RunFactoryMethodPattern {
public static void main(String [] arguments){ System.out.println("Example for the FactoryMethod pattern"); System.out.println(); System.out.println("Creating a Contact object"); System.out.println(); Contact someone = new Contact(); System.out.println("Creating a GUI editor for the Contact"); System.out.println(); 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 ItemEditor 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(" Contact class, and has appropriate fields for that class."); EditorGui runner = new EditorGui(someone.getEditor()); runner.createGui(); }
} class EditorGui implements ActionListener{
private JFrame mainFrame; private JTextArea display; private JButton update, exit; private JPanel controlPanel, displayPanel, editorPanel; private ItemEditor editor; public EditorGui(ItemEditor 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.rumitChanges(); display.setText(editor.toString()); } private void exitApplication(){ System.exit(0); }
} class Contact implements Editable, Serializable {
private String name; private String relationship; public ItemEditor getEditor() { return new ContactEditor(); } private class ContactEditor implements ItemEditor, 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 Editable {
public ItemEditor getEditor();
} interface ItemEditor {
public JComponent getGUI(); public void commitChanges();
}
</source>
Fly weight Factory
<source lang="java">
/* Software Architecture Design Patterns in Java by Partha Kuchana Auerbach Publications
- /
import java.util.HashMap; import java.util.StringTokenizer; import java.util.Vector; public class FlyweightTest {
public static void main(String[] args) throws Exception { Vector empList = initialize(); FlyweightFactory factory = FlyweightFactory.getInstance(); for (int i = 0; i < empList.size(); i++) { String s = (String) empList.elementAt(i); StringTokenizer st = new StringTokenizer(s, ","); String name = st.nextToken(); String title = st.nextToken(); String division = st.nextToken(); FlyweightIntr flyweight = factory.getFlyweight(division); //associate the flyweight //with the extrinsic data object. VCard card = new VCard(name, title, flyweight); card.print(); } } private static Vector initialize() { //for simplicity values are being hardcoded. Vector v = new Vector(); v.add("name1,title1,North"); v.add("name2,title2,South"); v.add("name3,title1,North"); v.add("name4,title3,East"); v.add("name5,title4,East"); v.add("name6,title2,East"); v.add("name7,title1,West"); v.add("name8,title3,West"); v.add("name9,title1,West"); v.add("name10,title6,South"); v.add("name11,title5,North"); v.add("name12,title1,North"); return v; }
} class FlyweightFactory {
private HashMap lstFlyweight; private static FlyweightFactory factory = new FlyweightFactory(); private FlyweightFactory() { lstFlyweight = new HashMap(); } public synchronized FlyweightIntr getFlyweight(String divisionName) { if (lstFlyweight.get(divisionName) == null) { FlyweightIntr fw = new Flyweight(divisionName); lstFlyweight.put(divisionName, fw); return fw; } else { return (FlyweightIntr) lstFlyweight.get(divisionName); } } public static FlyweightFactory getInstance() { return factory; } //Inner flyweight class private class Flyweight implements FlyweightIntr { private String company; private String address; private String city; private String state; private String zip; private void setValues(String cmp, String addr, String cty, String st, String zp) { company = cmp; address = addr; city = cty; state = st; zip = zp; } private Flyweight(String division) { // values are hard coded //for simplicity if (division.equals("North")) { setValues("CMP", "addr1", "cty1", "st1", "10000"); } if (division.equals("South")) { setValues("CMP", "addr2", "cty2", "st2", "20000"); } if (division.equals("East")) { setValues("CMP", "addr3", "cty3", "st3", "30000"); } if (division.equals("West")) { setValues("CMP", "addr4", "cty4", "st4", "40000"); } } public String getCompany() { return company; } public String getAddress() { return address; } public String getCity() { return city; } public String getState() { return state; } public String getZip() { return zip; } }// end of Flyweight
}// end of FlyweightFactory interface FlyweightIntr {
public String getCompany(); public String getAddress(); public String getCity(); public String getState(); public String getZip();
} class VCard {
String name; String title; FlyweightIntr objFW; public VCard(String n, String t, FlyweightIntr fw) { name = n; title = t; objFW = fw; } public void print() { System.out.println(name); System.out.println(title); System.out.println(objFW.getAddress() + "-" + objFW.getCity() + "-" + objFW.getState() + "-" + objFW.getZip()); System.out.println("----------------"); }
}
</source>
Illustrates use of Abstract Factory pattern
<source lang="java">
/* The Design Patterns Java Companion Copyright (C) 1998, by James W. Cooper IBM Thomas J. Watson Research Center
- /
import java.awt.Button; import java.awt.Checkbox; import java.awt.CheckboxGroup; import java.awt.Color; import java.awt.Dimension; import java.awt.Frame; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.Label; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; public class Gardener extends Frame implements ActionListener, ItemListener {
private Checkbox Vegie, Annual, Peren; private Button Center, Border, Shade, Quit; private Garden garden = null; private GardenPanel gardenPlot; private String borderPlant = "", centerPlant = "", shadePlant = ""; public Gardener() { super("Garden planner"); setGUI(); } //---------------------------------- private void setGUI() { setBackground(Color.lightGray); setLayout(new GridLayout(1, 2)); Panel left = new Panel(); add(left); Panel right = new Panel(); add(right); //create label and 3 radio buttons on left side left.setLayout(new GridLayout(4, 1)); left.add(new Label("Garden type")); CheckboxGroup grp = new CheckboxGroup(); Vegie = new Checkbox("Vegetable", grp, false); Annual = new Checkbox("Annual", grp, false); Peren = new Checkbox("Perennial", grp, false); left.add(Vegie); left.add(Annual); left.add(Peren); Vegie.addItemListener(this); Peren.addItemListener(this); Annual.addItemListener(this); //now create right side right.setLayout(new GridLayout(2, 1)); gardenPlot = new GardenPanel(); gardenPlot.setBackground(Color.white); Panel botRight = new Panel(); right.add(gardenPlot); right.add(botRight); Center = new Button("Central"); Border = new Button("Border"); Shade = new Button("Shade"); Quit = new Button("Quit"); botRight.add(Center); Center.addActionListener(this); botRight.add(Border); Border.addActionListener(this); botRight.add(Shade); Shade.addActionListener(this); botRight.add(Quit); Quit.addActionListener(this); setBounds(200, 200, 400, 300); setVisible(true); } //---------------------------------- public void actionPerformed(ActionEvent e) { Object obj = e.getSource(); if (obj == Center) setCenter(); if (obj == Border) setBorder(); if (obj == Shade) setShade(); if (obj == Quit) System.exit(0); } //---------------------------------- private void setCenter() { if (garden != null) centerPlant = garden.getCenter().getName(); gardenPlot.repaint(); } private void setBorder() { if (garden != null) borderPlant = garden.getBorder().getName(); gardenPlot.repaint(); } private void setShade() { if (garden != null) shadePlant = garden.getShade().getName(); gardenPlot.repaint(); } //---------------------------------- public void itemStateChanged(ItemEvent e) { Checkbox ck = (Checkbox) e.getSource(); garden = new GardenMaker().getGarden(ck.getLabel()); shadePlant = ""; centerPlant = ""; borderPlant = ""; gardenPlot.repaint(); } //---------------------------------- static public void main(String argv[]) { new Gardener(); } //-------------------------------- class GardenPanel extends Panel { public void paint(Graphics g) { Dimension sz = getSize(); g.setColor(Color.lightGray); g.fillArc(0, 0, 80, 80, 0, 360); g.setColor(Color.black); g.drawRect(0, 0, sz.width - 1, sz.height - 1); g.drawString(centerPlant, 100, 50); g.drawString(borderPlant, 75, 120); g.drawString(shadePlant, 10, 40); } }
} //end of Gardener class //============================================= class GardenMaker {
//Abstract Factory which returns one of three gardens private Garden gd; public Garden getGarden(String gtype) { gd = new VegieGarden(); //default if (gtype.equals("Perennial")) gd = new PerennialGarden(); if (gtype.equals("Annual")) gd = new AnnualGarden(); return gd; }
} abstract class Garden {
public abstract Plant getShade(); public abstract Plant getCenter(); public abstract Plant getBorder();
} class Plant {
String name; public Plant(String pname) { name = pname; //save name } public String getName() { return name; }
} class VegieGarden extends Garden {
public Plant getShade() { return new Plant("Broccoli"); } public Plant getCenter() { return new Plant("Corn"); } public Plant getBorder() { return new Plant("Peas"); }
} class AnnualGarden extends Garden {
public Plant getShade() { return new Plant("Coleus"); } public Plant getCenter() { return new Plant("Marigold"); } public Plant getBorder() { return new Plant("Alyssum"); }
} class PerennialGarden extends Garden {
public Plant getShade() { return new Plant("Astilbe"); } public Plant getCenter() { return new Plant("Dicentrum"); } public Plant getBorder() { return new Plant("Sedum"); }
}
</source>