Java/Design Pattern/Factory Pattern

Материал из Java эксперт
Перейти к: навигация, поиск

Abstract Factory Pattern- Example

/*
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





Abstract Factory Pattern in Java 2

//[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;
    }
}





Factory Method Pattern in 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();
}





Fly weight Factory

/*
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("----------------");
  }
}





Illustrates use of Abstract Factory pattern

/*
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");
 }
}