Java/Design Pattern/MVC Pattern — различия между версиями

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

Текущая версия на 06:50, 1 июня 2010

MVC Implementation

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





MVC Loop

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





MVC Pattern in Java 2

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