模型-视图-控件(Model-View-Controller,MVC)结构是以一种开发组件的方法,它将数据存储和数据处理从的数据的可视化表示中分离出来。存储和处理数据的组件称为模型(Model)。他包含组件的实际内容。表示数据的组件称为了视图(View),他处理组件所有必要的行为。控件(Controller)通常是一种用来获取数据的组件。
MVC优点:
1.可以使更多的视图显示成为可能。这样,可以通过一个模型共享数据。
2.可以简化复杂应用程序的编写。
模型包含数据,而视图使数据对外界可见。一旦一个视图与一个模型建立联系,它一定要与该模型同步。这样,可以确保模型的所有视图显示的数据都与模型的数据保持一致。要使模型与所属视图保持一致和同步,当视图中与数据相关的属性发生改变的时候,模型应当通知该视图。相应的,视图应当在收到模型的变化的通知后作出响应,重行显示受这些改变影响的视图区域。
Java事件委托模型提供了一种很好的架构以支持MVC组件模型的开发。这个模型可以具体实现为一个带适当的事件和事件监视器注册方法的源。视图可以实现为监视器。这样如果模型中的数据发生改变的时候,模型将会通知在模型已经注册的视图(也可以叫监听器),这样就能够保持模型与视图的数据保持一致。
下面是例子:
import java.awt.event.*;
import java.util.*;
public class CircleModel {
private double radius = 20;
private boolean filled;
private java.awt.Color color;
private ArrayList<ActionListener> actionListenerList;
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "radius"));
}
public boolean isFilled() {
return filled;
}
public void setFilled(boolean filled) {
this.filled = filled;
processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "filled"));
}
public java.awt.Color getColor() {
return color;
}
public void setColor(java.awt.Color color) {
this.color = color;
processEvent(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "color"));
}
public synchronized void removeActionListener(ActionListener l) {
if (actionListenerList != null && actionListenerList.contains(l)) {
actionListenerList.add(l);
}
}
public synchronized void addActionListener(ActionListener l) {
if (actionListenerList == null) {
actionListenerList = new ArrayList<ActionListener>();
}
actionListenerList.add(l);
}
private void processEvent(ActionEvent e) {
ArrayList list;
synchronized (this) {
if (actionListenerList == null) {
return;
}
list = (ArrayList) actionListenerList.clone();
}
for (int i = 0; i < list.size(); i++) {
ActionListener listener = (ActionListener) list.get(i);
listener.actionPerformed(e);
}
}
}
import java.awt.*;
import java.awt.event.*;
public class CircleView extends javax.swing.JPanel implements ActionListener {
private CircleModel model;
public void actionPerformed(ActionEvent actionEvent) {
repaint();
}
public void setModel(CircleModel newModel) {
model = newModel;
model.addActionListener(this);
repaint();
}
public CircleModel getModel() {
return model;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (model == null) {
return;
}
g.setColor(model.getColor());
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int) model.getRadius();
if (model.isFilled()) {
g.fillOval(xCenter - radius, yCenter - radius, 2 * radius, 2 * radius);
} else {
g.drawOval(xCenter - radius, yCenter - radius, 2 * radius, 2 * radius);
}
}
}
package mvx;
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class CircleController extends JPanel {
private CircleModel model;
private JTextField jtfRadius = new JTextField();
private JComboBox jcboFilled = new JComboBox(new Boolean[]{new Boolean(false), new Boolean(true)});
public CircleController() {
JPanel panel1 = new JPanel();
panel1.setLayout(new GridLayout(2, 1));
panel1.add(new Label("Radius"));
panel1.add(new JLabel("Filled"));
JPanel panel2 = new JPanel();
panel2.setLayout(new GridLayout(2, 1));
panel2.add(jtfRadius);
panel2.add(jcboFilled);
setLayout(new BorderLayout());
add(panel1, BorderLayout.WEST);
add(panel2, BorderLayout.CENTER);
jtfRadius.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (model == null) {
return;
}
model.setRadius(new Double(jtfRadius.getText()).doubleValue());
}
});
jcboFilled.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (model == null) {
return;
}
model.setFilled(((Boolean) jcboFilled.getSelectedItem()).booleanValue());
}
});
}
public void setModel(CircleModel model) {
this.model = model;
}
public CircleModel getModel() {
return model;
}
}
