Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Applied Java™ Patterns - Stephen Stelting, Olav Maassen.pdf
Скачиваний:
202
Добавлен:
24.05.2014
Размер:
2.84 Mб
Скачать

Prototype

The Address class in this example uses the Prototype pattern to create an address based on an existing entry. The core functionality for the pattern is defined in the interface Copyable.

Example A.26 Copyable.java

1.public interface Copyable{

2.public Object copy();

3.}

The Copyable interface defines a copy method and guarantees that any classes that implement the interface will define a copy operation. This example produces a shallow copy—that is, it copies the object references from the original address to the duplicate.

The code also demonstrates an important feature of the copy operation: not all fields must necessarily be duplicated. In this case, the address type is not copied to the new object. A user would manually specify a new address type from the PIM user interface.

Example A.27 Address.java

1.public class Address implements Copyable{

2.private String type;

3.private String street;

4.private String city;

5.private String state;

6.private String zipCode;

7.public static final String EOL_STRING =

8.System.getProperty("line.separator");

9.public static final String COMMA = ",";

10.public static final String HOME = "home";

11.public static final String WORK = "work";

13.public Address(String initType, String initStreet,

14.String initCity, String initState, String initZip){

15. type = initType;

16. street = initStreet;

17. city = initCity;

18. state = initState;

19. zipCode = initZip;

20. }

21.

22.public Address(String initStreet, String initCity,

23.String initState, String initZip){

24. this(WORK, initStreet, initCity, initState, initZip);

25.}

26.public Address(String initType){

27.type = initType;

28.}

29.public Address(){ }

30.

31.public String getType(){ return type; }

32.public String getStreet(){ return street; }

33.public String getCity(){ return city; }

34.public String getState(){ return state; }

35.public String getZipCode(){ return zipCode; }

37.public void setType(String newType){ type = newType; }

38.public void setStreet(String newStreet){ street = newStreet; }

39.public void setCity(String newCity){ city = newCity; }

40.public void setState(String newState){ state = newState; }

41.public void setZipCode(String newZip){ zipCode = newZip; }

42.

43.public Object copy(){

44.return new Address(street, city, state, zipCode);

45.}

46.

47.public String toString(){

48.return "\t" + street + COMMA + " " + EOL_STRING +

49. "\t" + city + COMMA + " " + state + " " + zipCode;

50.}

51.}

232

The RunPattern class demonstrates the use of this pattern by creating an Address object, then duplicating that object by calling its copy method. The fact that the Address objects return two different hash code values (numeric values that represent unique object identity) further confirms that the copy operation has produced a different object from the first.

Example A.28 RunPattern.java

1.public class RunPattern{

2.public static void main(String [] arguments){

3.System.out.println("Example for Prototype pattern");

4.System.out.println();

5.System.out.println("This example will create an Address object,");

6.System.out.println(" which it will then duplicate by calling the");

7.System.out.println(" object's clone method.");

8.System.out.println();

9.

10.System.out.println("Creating first address.");

11.Address address1 = new Address("8445 Silverado Trail", "Rutherford", "CA", "91734");

12.System.out.println("First address created.");

13.System.out.println(" Hash code = " + address1.hashCode());

14.System.out.println(address1);

15.System.out.println();

16.

17.System.out.println("Creating second address using the clone() method.");

18.Address address2 = (Address)address1.copy();

19.System.out.println("Second address created.");

20.System.out.println(" Hash code = " + address2.hashCode());

21.System.out.println(address2);

22.System.out.println();

23.

24.

25.}

26.}

233

Singleton

Application users want the option of undoing previous commands. To support that functionality, a history list is needed. That history list has to be accessible from everywhere in the PIM and only one instance of it is needed. Therefore, it’s a perfect candidate for the implementation of the Singleton pattern.

Example A.29 HistoryList.java

1.import java.util.ArrayList;

2.import java.util.Collections;

3.import java.util.List;

4.public class HistoryList{

5.private List history = Collections.synchronizedList(new ArrayList());

6.private static HistoryList instance = new HistoryList();

7.

8. private HistoryList(){ }

9.

10.public static HistoryList getInstance(){

11.return instance;

12.}

13.

14.public void addCommand(String command){

15.history.add(command);

16.}

17.

18.public Object undoCommand(){

19.return history.remove(history.size() - 1);

20.}

21.

22.public String toString(){

23.StringBuffer result = new StringBuffer();

24.for (int i = 0; i < history.size(); i++){

25.

result.append(" ");

26.

result.append(history.get(i));

27.

result.append("\n");

28.}

29.return result.toString();

30.}

31.}

The HistoryList maintains a static reference to an instance of itself, has a private constructor, and uses a static method getInstance to provide a single history list object to all parts of the PIM. The additional variable in HistoryList, history, is a List object used to track the command strings. The HistoryList provides two methods, addCommand and undoCommand to support adding and removing commands from the list.

The SingletonGui class provides a basic Swing GUI that demonstrates how the HistoryList might be used in a PIM editor. This GUI provides a basic set of commands: create contact, create appointment, undo, refresh and exit. For the create commands, you retrieve the HistoryList with a call to its static getInstance method, then call the addCommand method. For the undo command, you call getInstance followed by the undoCommand method. The refresh method calls the toString method in the HistoryList to retrieve the current set of history list entries for display.

Example A.30 SingletonGUI.java

1.import java.awt.Container;

2.import javax.swing.BoxLayout;

3.import javax.swing.JButton;

4.import javax.swing.JFrame;

5.import javax.swing.JPanel;

6.import javax.swing.JTextArea;

7.import java.awt.event.ActionEvent;

8.import java.awt.event.ActionListener;

9.import java.awt.event.WindowAdapter;

10.import java.awt.event.WindowEvent;

11.public class SingletonGui implements ActionListener{

12.private JFrame mainFrame;

13.private JTextArea display;

14.private JButton newContact, newAppointment, undo, refresh, exit;

15.private JPanel controlPanel, displayPanel;

16.private static int historyCount;

17.

18.public void createGui(){

19.mainFrame = new JFrame("Singleton Pattern Example");

234

20.Container content = mainFrame.getContentPane();

21.content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));

23.displayPanel = new JPanel();

24.display = new JTextArea(20, 60);

25.display.setEditable(false);

26.displayPanel.add(display);

27.content.add(displayPanel);

28.

29.controlPanel = new JPanel();

30.newContact = new JButton("Create contact");

31.newAppointment = new JButton("Create appointment");

32.undo = new JButton("Undo");

33.refresh = new JButton("Refresh");

34.exit = new JButton("Exit");

35.controlPanel.add(newContact);

36.controlPanel.add(newAppointment);

37.controlPanel.add(undo);

38.controlPanel.add(refresh);

39.controlPanel.add(exit);

40.content.add(controlPanel);

41.

42.newContact.addActionListener(this);

43.newAppointment.addActionListener(this);

44.undo.addActionListener(this);

45.refresh.addActionListener(this);

46.exit.addActionListener(this);

47.

48.mainFrame.addWindowListener(new WindowCloseManager());

49.mainFrame.pack();

50.mainFrame.setVisible(true);

51.}

52.

53.public void refreshDisplay(String actionMessage){

54.display.setText(actionMessage + "\nCOMMAND HISTORY:\n" +

55.

HistoryList.getInstance().toString());

56.

}

57.

 

58.public void actionPerformed(ActionEvent evt){

59.Object originator = evt.getSource();

60.if (originator == newContact){

61. addCommand(" New Contact");

62.}

63.else if (originator == newAppointment){

64. addCommand(" New Appointment");

65.}

66.else if (originator == undo){

67. undoCommand();

68.}

69.else if (originator == refresh){

70. refreshDisplay("");

71.}

72.else if (originator == exit){

73. exitApplication();

74.}

75.}

77.private class WindowCloseManager extends WindowAdapter{

78.public void windowClosing(WindowEvent evt){

79. exitApplication();

80.}

81.}

83.private void addCommand(String message){

84.HistoryList.getInstance().addCommand((++historyCount) + message);

85.refreshDisplay("Add Command: " + message);

86.}

87.

88.private void undoCommand(){

89.Object result = HistoryList.getInstance().undoCommand();

90.historyCount--;

91.refreshDisplay("Undo Command: " + result);

92.}

93.

94.private void exitApplication(){

95.System.exit(0);

96.}

97.}

235