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

System Pattern Code Examples

Model-View-Controller (MVC)

This code example provides a component-level MVC pattern to manage a contact in the Personal Information Manager. The ContactModel class provides the model for this demonstration, in this case storing the contact's first name, last name, title and organization.

Example A.199 ContactModel.java

1.import java.util.ArrayList;

2.import java.util.Iterator;

3.public class ContactModel{

4.private String firstName;

5.private String lastName;

6.private String title;

7.private String organization;

8.private ArrayList contactViews = new ArrayList();

10.public ContactModel(){

11.this(null);

12.}

13.public ContactModel(ContactView view){

14.firstName = "";

15.lastName = "";

16.title = "";

17.organization = "";

18.if (view != null){

19. contactViews.add(view);

20.}

21.}

23.public void addContactView(ContactView view){

24.if (!contactViews.contains(view)){

25. contactViews.add(view);

26.}

27.}

29.public void removeContactView(ContactView view){

30.contactViews.remove(view);

31.}

32.

33.public String getFirstName(){ return firstName; }

34.public String getLastName(){ return lastName; }

35.public String getTitle(){ return title; }

36.public String getOrganization(){ return organization; }

38.public void setFirstName(String newFirstName){ firstName = newFirstName; }

39.public void setLastName(String newLastName){ lastName = newLastName; }

40.public void setTitle(String newTitle){ title = newTitle; }

41.public void setOrganization(String newOrganization){ organization = newOrganization; }

43.public void updateModel(String newFirstName, String newLastName,

44.String newTitle, String newOrganization){

45.if (!isEmptyString(newFirstName)){

46.setFirstName(newFirstName);

47.}

48.if (!isEmptyString(newLastName)){

49.setLastName(newLastName);

50.}

51.if (!isEmptyString(newTitle)){

52.setTitle(newTitle);

53.}

54.if (!isEmptyString(newOrganization)){

55.setOrganization(newOrganization);

56.}

57.updateView();

58.}

59.

60.private boolean isEmptyString(String input){

61.return ((input == null) || input.equals(""));

62.}

63.

64.private void updateView(){

65.Iterator notifyViews = contactViews.iterator();

327

66.while (notifyViews.hasNext()){

67.((ContactView)notifyViews.next()).refreshContactView(firstName, lastName, title,

organization);

68.}

69.}

70.}

The ContactModel maintains an ArrayList of ContactView objects, updating them whenever the model data changes. The standard behavior for all views is defined by the ContactView interface method

refreshContactView.

Example A.200 ContactView.java

1.public interface ContactView{

2.public void refreshContactView(String firstName,

3.String lastName, String title, String organization);

4.}

Two views are used in this example. The first, ContactDisplayView, displays the updated model information but does not support a controller, an example of “view-only” behavior.

Example A.201 ContactDisplayView.java

1.import javax.swing.JPanel;

2.import javax.swing.JScrollPane;

3.import javax.swing.JTextArea;

4.import java.awt.BorderLayout;

5.public class ContactDisplayView extends JPanel implements ContactView{

6.private JTextArea display;

7.

8.public ContactDisplayView(){

9.createGui();

10.}

11.

12.public void createGui(){

13.setLayout(new BorderLayout());

14.display = new JTextArea(10, 40);

15.display.setEditable(false);

16.JScrollPane scrollDisplay = new JScrollPane(display);

17.this.add(scrollDisplay, BorderLayout.CENTER);

18.}

19.

20.public void refreshContactView(String newFirstName,

21.String newLastName, String newTitle, String newOrganization){

22.display.setText("UPDATED CONTACT:\nNEW VALUES:\n" +

23. "\tName: " + newFirstName + " " + newLastName + 24. "\n" + "\tTitle: " + newTitle + "\n" +

25. "\tOrganization: " + newOrganization);

26.}

27.}

The second view is ContactEditView, which allows a user to update the contact defined by the model.

Example A.202 ContactEditView.java

1.import javax.swing.BoxLayout;

2.import javax.swing.JButton;

3.import javax.swing.JLabel;

4.import javax.swing.JTextField;

5.import javax.swing.JPanel;

6.import java.awt.GridLayout;

7.import java.awt.BorderLayout;

8.import java.awt.event.ActionListener;

9.import java.awt.event.ActionEvent;

10.public class ContactEditView extends JPanel implements ContactView{

11.private static final String UPDATE_BUTTON = "Update";

12.private static final String EXIT_BUTTON = "Exit";

13.private static final String CONTACT_FIRST_NAME = "First Name ";

14.private static final String CONTACT_LAST_NAME = "Last Name ";

15.private static final String CONTACT_TITLE = "Title ";

16.private static final String CONTACT_ORG = "Organization ";

17.private static final int FNAME_COL_WIDTH = 25;

18.private static final int LNAME_COL_WIDTH = 40;

19.private static final int TITLE_COL_WIDTH = 25;

20.private static final int ORG_COL_WIDTH = 40;

21.private ContactEditController controller;

328

22.private JLabel firstNameLabel, lastNameLabel, titleLabel, organizationLabel;

23.private JTextField firstName, lastName, title, organization;

24.private JButton update, exit;

25.

26.public ContactEditView(ContactModel model){

27.controller = new ContactEditController(model, this);

28.createGui();

29.}

30.public ContactEditView(ContactModel model, ContactEditController newController){

31.controller = newController;

32.createGui();

33.}

34.

35.public void createGui(){

36.update = new JButton(UPDATE_BUTTON);

37.exit = new JButton(EXIT_BUTTON);

38.

39.firstNameLabel = new JLabel(CONTACT_FIRST_NAME);

40.lastNameLabel = new JLabel(CONTACT_LAST_NAME);

41.titleLabel = new JLabel(CONTACT_TITLE);

42.organizationLabel = new JLabel(CONTACT_ORG);

43.

44.firstName = new JTextField(FNAME_COL_WIDTH);

45.lastName = new JTextField(LNAME_COL_WIDTH);

46.title = new JTextField(TITLE_COL_WIDTH);

47.organization = new JTextField(ORG_COL_WIDTH);

49.JPanel editPanel = new JPanel();

50.editPanel.setLayout(new BoxLayout(editPanel, BoxLayout.X_AXIS));

52.JPanel labelPanel = new JPanel();

53.labelPanel.setLayout(new GridLayout(0, 1));

55.labelPanel.add(firstNameLabel);

56.labelPanel.add(lastNameLabel);

57.labelPanel.add(titleLabel);

58.labelPanel.add(organizationLabel);

60.

editPanel.add(labelPanel);

61.

 

62.JPanel fieldPanel = new JPanel();

63.fieldPanel.setLayout(new GridLayout(0, 1));

65.fieldPanel.add(firstName);

66.fieldPanel.add(lastName);

67.fieldPanel.add(title);

68.fieldPanel.add(organization);

70.

editPanel.add(fieldPanel);

71.

 

72.JPanel controlPanel = new JPanel();

73.controlPanel.add(update);

74.controlPanel.add(exit);

75.update.addActionListener(controller);

76.exit.addActionListener(new ExitHandler());

78.setLayout(new BorderLayout());

79.add(editPanel, BorderLayout.CENTER);

80.add(controlPanel, BorderLayout.SOUTH);

81.}

82.

83.public Object getUpdateRef(){ return update; }

84.public String getFirstName(){ return firstName.getText(); }

85.public String getLastName(){ return lastName.getText(); }

86.public String getTitle(){ return title.getText(); }

87.public String getOrganization(){ return organization.getText(); }

89.public void refreshContactView(String newFirstName,

90.String newLastName, String newTitle,

91.String newOrganization){

92.firstName.setText(newFirstName);

93.lastName.setText(newLastName);

94.title.setText(newTitle);

95.organization.setText(newOrganization);

96.}

97.

98.private class ExitHandler implements ActionListener{

99.public void actionPerformed(ActionEvent event){

329

100.System.exit(0);

101.}

102.}

103.}

The updates to the model are possible due to the controller associated with the ContactEditView. In this example, Java event-handling features (and by extension the Observer pattern) manage communication between the

ContactEditView and its associated Controller. ContactEditController updates the ContactModel when

the update behavior is triggered by the ContactEditView, calling the method updateModel with new data provided by the editable fields of its associated view.

Example A.203 ContactEditController.java

1. import java.awt.event.*;

2.

3.public class ContactEditController implements ActionListener{

4.private ContactModel model;

5.private ContactEditView view;

6.

7.public ContactEditController(ContactModel m, ContactEditView v){

8.model = m;

9.view = v;

10.}

11.

12.public void actionPerformed(ActionEvent evt){

13.Object source = evt.getSource();

14.if (source == view.getUpdateRef()){

15. updateModel();

16.}

17.}

19.private void updateModel(){

20.String firstName = null;

21.String lastName = null;

22.if (isAlphabetic(view.getFirstName())){

23. firstName = view.getFirstName();

24.}

25.if (isAlphabetic(view.getLastName())){

26. lastName = view.getLastName();

27.}

28.model.updateModel( firstName, lastName,

29. view.getTitle(), view.getOrganization());

30. }

31.

32.private boolean isAlphabetic(String input){

33.char [] testChars = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};

34.for (int i = 0; i < testChars.length; i++){

35.

if (input.indexOf(testChars[i]) != -1){

36.

return false;

37.

}

38.}

39.return true;

40.}

41.}

RunPattern runs the demonstration for this pattern, creating the model and Swing GUIs for both of the associated views. The update information provided by the ContactEditView is reflected in the ContactDisplayView, demonstrat-ing the fact that a single model can provide information to multiple view objects.

Example A.204 RunPattern.java

1.public interface ContactView{

2.public void refreshContactView(String firstName,

3.String lastName, String title, String organization);

4.}

330