首先是创建一个模型(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);
}
}