首先是创建一个模型(Model)。PropertyChangeSupport成员变量,是事件委托模型中的发布订阅机制。它允许试图注册给Model,并接收Model状态的变化通告。
import
java.beans.PropertyChangeListener;
import
java.beans.PropertyChangeSupport;
public
class
Model
...
{ private PropertyChangeSupport changeSupport = new PropertyChangeSupport( this ); private boolean loginStatus; private String login; private String password; public Model() ... { loginStatus = false ; } public void setLogin(String login) ... { this .login = login; } public void setPassword(String password) ... { this .password = password; } public boolean getLoginStatus() ... { return loginStatus; } public boolean getAllowed() ... { boolean allowed = false ; if (login == " abc " && password == " abc " ) allowed = true ; else allowed = false ; return allowed; } public void setLoginStatus( boolean status) ... { boolean old = this .loginStatus; this .loginStatus = status; changeSupport.firePropertyChange( " model.loginStatus " , old, status); } public void login(String login,String password) ... { setLogin(login); setPassword(password); if (getAllowed()) ... { if (getLoginStatus()) ... { setLoginStatus( false ); } else ... { setLoginStatus( true ); } } else setLoginStatus(false ); } public void addPropertyChangeListener(PropertyChangeListener listener) ... { changeSupport.addPropertyChangeListener(listener); } }
然后是创建视图。CenterPanel用来输入用户数据。WorkPanel实现了PropertyChangeListener接口,这就使得WorkPanel可以注册到应用程序Model,并且当Model变化时使修改通告被发布给它。WorkPanel被作为PropertyChangeListener被注册到Model。这将在界面和域逻辑之间提供了低耦合,允许视图在Model发生变化时被修改。
import
java.awt.GridLayout;
import
javax.swing.JLabel;
import
javax.swing.JPanel;
import
javax.swing.JTextField;
import
javax.swing.JPasswordField;
public
class
CenterPanel
extends
JPanel
...
{ static final long serialVersionUID = 1L ; private JTextField login = new JTextField( 15 ); private JPasswordField password = new JPasswordField( 15 ); public CenterPanel() ... { setLayout( new GridLayout( 2 , 2 )); add( new JLabel( " Login: " )); add(login); add( new JLabel( " Password: " )); add(password); } public String getLogin() ... { return login.getText(); } public String getPassword() ... { return password.getText(); } }
import
java.awt.BorderLayout;
import
java.beans.PropertyChangeEvent;
import
java.beans.PropertyChangeListener;
import
javax.swing.Action;
import
javax.swing.JButton;
import
javax.swing.JLabel;
import
javax.swing.JPanel;
public
class
WorkPanel
extends
JPanel
implements
PropertyChangeListener
...
{ static final long serialVersionUID = 1L ; private Model model; private JPanel center; private JPanel buttonPanel = new JPanel(); private JLabel loginStatusLabel = new JLabel( " " ); public WorkPanel(JPanel center, Model model) ... { this .center = center; this .model = model; init(); } private void init() ... { setLayout( new BorderLayout()); add(center ,BorderLayout.CENTER); add(buttonPanel, BorderLayout.SOUTH); add(loginStatusLabel , BorderLayout.NORTH); } public void propertyChange(PropertyChangeEvent evt) ... { if (evt.getPropertyName().equals( " model.loginStatus " )) ... { Boolean status = (Boolean)evt.getNewValue(); if (status.booleanValue()) ... { loginStatusLabel.setText( " Login is sucessful " ); } else ... { loginStatusLabel.setText( " Login Failed " ); } } } public void addButton (String name , Action action) ... { JButton button = new JButton(name); button.addActionListener(action); buttonPanel.add(button); } }
接着是控制器。控制器的目的是作为模型修改的入口来提供服务。Action类通过组件addActionListener()方法注册到一个或者多个图形组件中。以下两个Action,一个尝试使用Model进行登录,一个用于退出应用程序。
import
java.awt.event.ActionEvent;
import
javax.swing.AbstractAction;
public
class
LoginAction
extends
AbstractAction
...
{ static final long serialVersionUID = 1L ; private Model model; private CenterPanel panel; public LoginAction(Model model,CenterPanel panel) ... { this .model = model; this .panel = panel; } public void actionPerformed(ActionEvent e) ... { System.out.println( " Login Action: " + panel.getLogin() + " " + panel.getPassword()); model.login(panel.getLogin(), panel.getPassword()); } }
import
java.awt.event.ActionEvent;
import
javax.swing.AbstractAction;
import
javax.swing.JFrame;
import
javax.swing.JOptionPane;
public
class
ExitAction
extends
AbstractAction
...
{ static final long serialVersionUID = 1L ; public void actionPerformed(ActionEvent e) ... { JFrame frame = new JFrame(); int response = JOptionPane.showConfirmDialog(frame, " Exit Application? " , " Exit " , JOptionPane.OK_CANCEL_OPTION); if (JOptionPane.YES_OPTION == response) ... { System.exit( 0 ); } } }
最后,Application类用来初始化。它创建关联,建立起了MVC逻辑设计原则。 1、创建到Model类的关联; 2、创建View来显示Swing接口; 3、创建Action类,表示控制器并且将通过命令按钮来注册它们; 4、最后用Swing来显示应用程序;
import
java.awt.event.WindowAdapter;
import
java.awt.event.WindowEvent;
import
javax.swing.JFrame;
import
javax.swing.JOptionPane;
public
class
Application
extends
JFrame
...
{ static final long serialVersionUID = 1L ; private Model model; public Application(Model model) ... { this .model = model; CenterPanel center = new CenterPanel(); WorkPanel work = new WorkPanel(center,model); work.addButton( " login " , new LoginAction(model,center)); work.addButton( " exit " , new ExitAction()); model.addPropertyChangeListener(work); setTitle( " MVC Pattern Application " ); getContentPane().add(work); pack(); setVisible( true ); addWindowListener( new WindowAdapter() ... { public void windowClosing(WindowEvent e) ... { int response = JOptionPane.showConfirmDialog( null , " Exit Application? " , " Exit " , JOptionPane.OK_CANCEL_OPTION); if (JOptionPane.YES_OPTION == response) ... { // dispose(); // finalize(); System.exit( 0 ); } } }); } public static void main(String[] args) ... { Model model = new Model(); Application application = new Application(model); } }