Java/Design Pattern/MVC Pattern

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

MVC Implementation

   <source lang="java">

/*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Point2D; import java.io.IOException; import java.util.ArrayList; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /**

* MVC Implementation
* 
* @author Ian Darwin, http://www.darwinsys.ru/
* @version $Id: MVCDemo.java,v 1.3 2004/03/21 00:44:36 ian Exp $
*/

public class MVCDemo {

 /** "main program" method - construct and show */
 public static void main(String[] av) {
   // Create the data model
   final Model model = new Model();
   // create a JFrame to hold it all.
   final JFrame f = new JFrame("MVC");
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   Container cp = f.getContentPane();
   JPanel tp = new JPanel();
   cp.add(tp, BorderLayout.NORTH);
   tp.add(new JLabel("New value:"));
   final JTextField tf = new JTextField(10);
   tp.add(tf);
   tf.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent evt) {
       model.add(tf.getText());
       tf.setText("");
     }
   });
   JPanel p = new JPanel();
   // The first View is a JTextArea subclassed to have
   // an easy way of setting the data from a java.util.List
   final TextView tv = new TextView();
   model.addChangeListener(new ChangeListener() {
     public void stateChanged(ChangeEvent evt) {
       Object o = evt.getSource();
       Model m = (Model) o;
       tv.setListData(m.getData());
     }
   });
   tv.setBackground(Color.RED);
   tv.setSize(100, 100);
   p.add(tv);
   // The second View is the simplistic Grapher program from
   // the Java Cookbook "Graphics" chapter (../graphics/Grapher.java)
   final Grapher vv = new Grapher();
   model.addChangeListener(new ChangeListener() {
     public void stateChanged(ChangeEvent evt) {
       Object o = evt.getSource();
       Model m = (Model) o;
       vv.setListData(m.getData());
     }
   });
   vv.setBackground(Color.YELLOW);
   vv.setSize(100, 100);
   p.add(vv);
   cp.add(p, BorderLayout.CENTER);
   f.pack();
   f.setLocation(100, 100);
   f.setVisible(true);
 }

} class TextView extends JTextArea {

 public TextView() {
   super(20, 20);
 }
 public void setListData(ArrayList l) {
   setText("");
   for (int i = 0; i < l.size(); i++) {
     append((String) l.get(i));
     append("\n");
   }
 }

} class Model {

 private ArrayList list = new ArrayList();
 public void add(String s) {
   list.add(s);
   fireChange();
 }
 public ArrayList getData() {
   return list;
 }
 // Sun recommends using javax.swing.EventListenerList, but this is easier
 ArrayList changeListeners = new ArrayList();
 public void addChangeListener(ChangeListener cl) {
   changeListeners.add(cl);
 }
 public void removeChangeListener(ChangeListener cl) {
   changeListeners.remove(cl);
 }
 protected void fireChange() {
   ChangeEvent evt = new ChangeEvent(this);
   for (int i = 0; i < changeListeners.size(); i++) {
     ChangeListener cl = (ChangeListener) changeListeners.get(i);
     cl.stateChanged(evt);
   }
 }

} class Grapher extends JPanel {

 /** Multiplier for range to allow room for a border */
 public final static double BORDERFACTOR = 1.1f;
 /** The list of Point points. */
 protected ArrayList data;
 /** The minimum and maximum X values */
 protected double minx = Integer.MAX_VALUE, maxx = Integer.MIN_VALUE;
 /** The minimum and maximum Y values */
 protected double miny = Integer.MAX_VALUE, maxy = Integer.MIN_VALUE;
 /** The range of X and Y values */
 protected double xrange, yrange;
 public Grapher() {
   data = new ArrayList();
   figure();
 }
 /**
  * Set the list data from a list of Strings, where the x coordinate is
  * incremented automatically, and the y coordinate is made from the String
  * in the list.
  */
 public void setListDataFromYStrings(ArrayList newData) {
   data.clear();
   for (int i = 0; i < newData.size(); i++) {
     Point2D p = new Point2D.Double();
     p.setLocation(i, java.lang.Double.parseDouble((String) newData
         .get(i)));
     data.add(p);
   }
   figure();
 }
 /** Set the list from an existing List, as from GraphReader.read() */
 public void setListData(ArrayList newData) {
   data = newData;
   figure();
 }
 /** Compute new data when list changes */
 private void figure() {
   // find min & max
   for (int i = 0; i < data.size(); i++) {
     Point2D d = (Point2D) data.get(i);
     if (d.getX() < minx)
       minx = d.getX();
     if (d.getX() > maxx)
       maxx = d.getX();
     if (d.getY() < miny)
       miny = d.getY();
     if (d.getY() > maxy)
       maxy = d.getY();
   }
   // Compute ranges
   xrange = (maxx - minx) * BORDERFACTOR;
   yrange = (maxy - miny) * BORDERFACTOR;
 }
 /**
  * Called when the window needs painting. Computes X and Y range, scales.
  */
 public void paintComponent(Graphics g) {
   super.paintComponent(g);
   Dimension s = getSize();
   if (data.size() < 2) {
     g.drawString("Insufficient data: " + data.size(), 10, 40);
     return;
   }
   // Compute scale factors
   double xfact = s.width / xrange;
   double yfact = s.height / yrange;
   // Scale and plot the data
   for (int i = 0; i < data.size(); i++) {
     Point2D d = (Point2D) data.get(i);
     double x = (d.getX() - minx) * xfact;
     double y = (d.getY() - miny) * yfact;
     // Draw a 5-pixel rectangle centered, so -2 both x and y.
     // AWT numbers Y from 0 down, so invert:
     g.drawRect(((int) x) - 2, s.height - 2 - (int) y, 5, 5);
   }
 }
 public Dimension getPreferredSize() {
   return new Dimension(150, 150);
 }
 public static void main(String[] args) throws IOException {
   final JFrame f = new JFrame("Grapher");
   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   Grapher grapher = new Grapher();
   f.setContentPane(grapher);
   f.setLocation(100, 100);
   f.pack();
   ArrayList data = new ArrayList();
       data.add("a");
   grapher.setListData(data);
   f.setVisible(true);
 }

}


      </source>
   
  
 
  



MVC Loop

   <source lang="java">

/*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002. All rights
* reserved. Software written by Ian F. Darwin and others. $Id: LICENSE,v 1.8
* 2004/02/09 03:33:38 ian Exp $
* 
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* 
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS"" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee cup"
* logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

// Investigate if you can get into a loop with a Swing-based MVC app; // in particular, if you do setSelectedIndex on a choice, does it // generate a secondary event? Push the button and see! // If it does, you must be careful to avoid event propagation loops. // This example doesn"t show it, but you can loop with other implementations. // For example, if a changed() method updates the model"s data. import java.awt.Button; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JComboBox; import javax.swing.JFrame; public class MVCLoop {

 public static void main(String[] a) {
   Button b;
   final JComboBox ch;
   JFrame f = new JFrame("Testing");
   Container cp = f.getContentPane();
   cp.setLayout(new FlowLayout());
   b = new Button("Set");
   ch = new JComboBox();
   cp.add(b);
   b.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       int cur = ch.getSelectedIndex();
       int len = ch.getItemCount();
       cur++;
       cur %= len;
       ch.setSelectedIndex(cur);
     }
   });
   ch.addItem("En/ett");
   ch.addItem("Zwei");
   ch.addItem("Tres");
   ch.addItem("Four");
   ch.addItem("Funf");
   ch.addItem("Seis");
   ch.addItem("Siete");
   ch.addItem("Octo");
   cp.add(ch);
   ch.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
       System.out.println(e);
     }
   });
   f.pack();
   f.setVisible(true);
 }

}


      </source>
   
  
 
  



MVC Pattern in Java 2

   <source lang="java">

//[C] 2002 Sun Microsystems, Inc.--- import java.awt.BorderLayout; 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.util.ArrayList; import java.util.Iterator; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; public class RunMVCPattern {

   public static void main(String [] arguments){
       System.out.println("Example for the MVC pattern");
       System.out.println();
       System.out.println("In this example, a Contact is divided into");
       System.out.println(" Model, View and Controller components.");
       System.out.println();
       System.out.println("To illustrate the flexibility of MVC, the same");
       System.out.println(" Model will be used to provide information");
       System.out.println(" to two View components.");
       System.out.println();
       System.out.println("One view, ContactEditView, will provide a Contact");
       System.out.println(" editor window and will be paired with a controller");
       System.out.println(" called ContactEditController.");
       System.out.println();
       System.out.println("The other view, ContactDisplayView, will provide a");
       System.out.println(" display window which will reflect the changes made");
       System.out.println(" in the editor window. This view does not support");
       System.out.println(" user interaction, and so does not provide a controller.");
       System.out.println();
       
       System.out.println("Creating ContactModel");
       ContactModel model = new ContactModel();
       
       System.out.println("Creating ContactEditView and ContactEditController");
       ContactEditView editorView = new ContactEditView(model);
       model.addContactView(editorView);
       createGui(editorView, "Contact Edit Window");
       
       System.out.println("Creating ContactDisplayView");
       ContactDisplayView displayView = new ContactDisplayView();
       model.addContactView(displayView);
       createGui(displayView, "Contact Display Window");
   }
   
   private static void createGui(JPanel contents, String title){
       JFrame applicationFrame = new JFrame(title);
       applicationFrame.getContentPane().add(contents);
       applicationFrame.addWindowListener(new WindowCloseManager());
       applicationFrame.pack();
       applicationFrame.setVisible(true);
   }
   
   private static class WindowCloseManager extends WindowAdapter{
       public void windowClosing(WindowEvent evt){
           System.exit(0);
       }
   }

} //Model class Contact{

   private String firstName;
   private String lastName;
   private String title;
   private String organization;
   
   private ContactView view;
   
   public Contact(ContactView v){
       
       firstName = "";
       lastName = "";
       title = "";
       organization = "";
       
       view = v;
   }
   
   public String getFirstName(){
       return firstName;
   }
   
   public String getLastName(){
       return lastName;
   }
   
   public String getTitle(){
       return title;
   }
   
   public String getOrganization(){
       return organization;
   }
   
   public void setFirstName(String newFirstName){
       firstName = newFirstName;
   }
   
   public void setLastName(String newLastName){
       lastName = newLastName;
   }
   
   public void setTitle(String newTitle){
       title = newTitle;
   }
   
   public void setOrganization(String newOrganization){
       organization = newOrganization;
   }
   
   public void updateModel(String newFirstName,
       String newLastName, String newTitle,
       String newOrganization){
       
       if ((newFirstName != null) && !newFirstName.equals("")){
           setFirstName(newFirstName);
       }
       
       if ((newLastName != null) && !newLastName.equals("")){
           setLastName(newLastName);
       }
       
       if ((newTitle != null) && !newTitle.equals("")){
           setTitle(newTitle);
       }
       
       if ((newOrganization != null) && !newOrganization.equals("")){
           setOrganization(newOrganization);
       }
       
       updateView();
   }
   
   private void updateView(){
       view.refreshContactView(firstName, lastName, title, organization);
   }

}

interface ContactView{

   public void refreshContactView(String firstName,
       String lastName, String title, String organization);

} class ContactModel{

   private String firstName;
   private String lastName;
   private String title;
   private String organization;
   private ArrayList contactViews = new ArrayList();
   
   public ContactModel(){
       this(null);
   }
   public ContactModel(ContactView view){
       firstName = "";
       lastName = "";
       title = "";
       organization = "";
       if (view != null){
           contactViews.add(view);
       }
   }
   
   public void addContactView(ContactView view){
       if (!contactViews.contains(view)){
           contactViews.add(view);
       }
   }
   
   public void removeContactView(ContactView view){
       contactViews.remove(view);
   }
   
   public String getFirstName(){ return firstName; }
   public String getLastName(){ return lastName; }
   public String getTitle(){ return title; }
   public String getOrganization(){ return organization; }
   
   public void setFirstName(String newFirstName){ firstName = newFirstName; }
   public void setLastName(String newLastName){ lastName = newLastName; }
   public void setTitle(String newTitle){ title = newTitle; }
   public void setOrganization(String newOrganization){ organization = newOrganization; }
   
   public void updateModel(String newFirstName, String newLastName,
       String newTitle, String newOrganization){
       if (!isEmptyString(newFirstName)){
           setFirstName(newFirstName);
       }
       if (!isEmptyString(newLastName)){
           setLastName(newLastName);
       }
       if (!isEmptyString(newTitle)){
           setTitle(newTitle);
       }
       if (!isEmptyString(newOrganization)){
           setOrganization(newOrganization);
       }
       updateView();
   }
   
   private boolean isEmptyString(String input){
       return ((input == null) || input.equals(""));
   }
   
   private void updateView(){
       Iterator notifyViews = contactViews.iterator();
       while (notifyViews.hasNext()){
           ((ContactView)notifyViews.next()).refreshContactView(firstName, lastName, title, organization);
       }
   }

}

class ContactEditView extends JPanel implements ContactView{

   private static final String UPDATE_BUTTON = "Update";
   private static final String EXIT_BUTTON = "Exit";
   private static final String CONTACT_FIRST_NAME = "First Name  ";
   private static final String CONTACT_LAST_NAME = "Last Name  ";
   private static final String CONTACT_TITLE = "Title  ";
   private static final String CONTACT_ORG = "Organization  ";
   private static final int FNAME_COL_WIDTH = 25;
   private static final int LNAME_COL_WIDTH = 40;
   private static final int TITLE_COL_WIDTH = 25;
   private static final int ORG_COL_WIDTH = 40;
   private ContactEditController controller;
   private JLabel firstNameLabel, lastNameLabel, titleLabel, organizationLabel;
   private JTextField firstName, lastName, title, organization;
   private JButton update, exit;
   
   public ContactEditView(ContactModel model){
       controller = new ContactEditController(model, this);
       createGui();
   }
   public ContactEditView(ContactModel model, ContactEditController newController){
       controller = newController;
       createGui();
   }
   
   public void createGui(){
       update = new JButton(UPDATE_BUTTON);
       exit = new JButton(EXIT_BUTTON);
       
       firstNameLabel = new JLabel(CONTACT_FIRST_NAME);
       lastNameLabel = new JLabel(CONTACT_LAST_NAME);
       titleLabel = new JLabel(CONTACT_TITLE);
       organizationLabel = new JLabel(CONTACT_ORG);
       
       firstName = new JTextField(FNAME_COL_WIDTH);
       lastName = new JTextField(LNAME_COL_WIDTH);
       title = new JTextField(TITLE_COL_WIDTH);
       organization = new JTextField(ORG_COL_WIDTH);
       
       JPanel editPanel = new JPanel();
       editPanel.setLayout(new BoxLayout(editPanel, BoxLayout.X_AXIS));
       
       JPanel labelPanel = new JPanel();
       labelPanel.setLayout(new GridLayout(0, 1));
       
       labelPanel.add(firstNameLabel);
       labelPanel.add(lastNameLabel);
       labelPanel.add(titleLabel);
       labelPanel.add(organizationLabel);
       
       editPanel.add(labelPanel);
       
       JPanel fieldPanel = new JPanel();
       fieldPanel.setLayout(new GridLayout(0, 1));
       
       fieldPanel.add(firstName);
       fieldPanel.add(lastName);
       fieldPanel.add(title);
       fieldPanel.add(organization);
       
       editPanel.add(fieldPanel);
       
       JPanel controlPanel = new JPanel();
       controlPanel.add(update);
       controlPanel.add(exit);
       update.addActionListener(controller);
       exit.addActionListener(new ExitHandler());
       
       setLayout(new BorderLayout());
       add(editPanel, BorderLayout.CENTER);
       add(controlPanel, BorderLayout.SOUTH);
   }
   
   public Object getUpdateRef(){ return update; }
   public String getFirstName(){ return firstName.getText(); }
   public String getLastName(){ return lastName.getText(); }
   public String getTitle(){ return title.getText(); }
   public String getOrganization(){ return organization.getText(); }
   
   public void refreshContactView(String newFirstName,
       String newLastName, String newTitle,
       String newOrganization){
       firstName.setText(newFirstName);
       lastName.setText(newLastName);
       title.setText(newTitle);
       organization.setText(newOrganization);
   }
   
   private class ExitHandler implements ActionListener{
       public void actionPerformed(ActionEvent event){
           System.exit(0);
       }
   }

} class ContactEditController implements ActionListener{

   private ContactModel model;
   private ContactEditView view;
   
   public ContactEditController(ContactModel m, ContactEditView v){
       model = m;
       view = v;
   }
   
   public void actionPerformed(ActionEvent evt){
       Object source = evt.getSource();
       if (source == view.getUpdateRef()){
           updateModel();
       }
   }
   
   private void updateModel(){
       String firstName = null;
       String lastName = null;
       if (isAlphabetic(view.getFirstName())){
           firstName = view.getFirstName();
       }
       if (isAlphabetic(view.getLastName())){
           lastName = view.getLastName();
       }
       model.updateModel( firstName, lastName,
           view.getTitle(), view.getOrganization());
   }
   
   private boolean isAlphabetic(String input){
       char [] testChars = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
       for (int i = 0; i < testChars.length; i++){
           if (input.indexOf(testChars[i]) != -1){
               return false;
           }
       }
       return true;
   }

} class ContactDisplayView extends JPanel implements ContactView{

   private JTextArea display;
   
   public ContactDisplayView(){
       createGui();
   }
   
   public void createGui(){
       setLayout(new BorderLayout());
       display = new JTextArea(10, 40);
       display.setEditable(false);
       JScrollPane scrollDisplay = new JScrollPane(display);
       this.add(scrollDisplay, BorderLayout.CENTER);
   }
   
   public void refreshContactView(String newFirstName,
       String newLastName, String newTitle, String newOrganization){
       display.setText("UPDATED CONTACT:\nNEW VALUES:\n" +
           "\tName: " + newFirstName + " " + newLastName +
            "\n" + "\tTitle: " + newTitle + "\n" +
           "\tOrganization: " + newOrganization);
   }

}


      </source>