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

“Look but don’t touch” views – Not all views require a controller. Some provide only a visual representation of model data, but don’t support any changes to the model from that view.

Related Patterns

Related patterns include the following:

Observer (page 94) – The MVC pattern often uses the Observable pattern to manage communication. This is usually done for the following parts of the system:

Between the view and controller, so that a change in the view triggers a response in the controller

Between the model and view, so the view is notified of a change in the model.

Strategy (page 114) – The controller is often implemented with the Strategy pattern to simplify changing controllers.

Example

Note:

For a full working example of this code example, with additional supporting classes and/or a RunPattern class, see “ ” on page 501 of the “ ” appendix.

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 4.1 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; }

143

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

42.

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();

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 4.2 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 4.3 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.}

144

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

Example 4.4 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;

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);

145

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){

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 4.5 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;

146

40.}

41.}

147