MVC上特定字段的java观察者模式
在MVC模式上,这是模型通知视图的最佳选项(如果这首先是正确的方法),其中,从模型存储的所有数据字段中,只有几个字段被更新。特别是当我们只想更新视图的特定字段时
我目前正在使用一个MVC模式与Observer/Subscriber(JavaSwing),如下所述:https://stackoverflow.com/a/6963529但是当模型更新时,它会更改视图中的所有内容。当调用update()
函数时,无法确定模型中的哪个字段发生了更改,以便只更新视图中所需的字段
我读了这个主题:https://softwareengineering.stackexchange.com/a/359008,还有这个:https://stackoverflow.com/a/9815189,我认为它很有用,但对于后面的主题,我不太明白如何在变量(int、float等)上设置propertyChangeListener。也与此相关:https://stackoverflow.com/a/9815189
软件开始运行的主类:
public class Main {
public static void main(String[] args) {
Model m = new Model();
View v = new View(m);
Controller c = new Controller(m, v);
c.initController();
}
}
所以我在模型上的代码是:
public class Model extends Observable {
//...
private float speed;
private int batteryPercentage;
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
setChanged();
notifyObservers();
}
public int getBatteryPercentage() {
return batteryPercentage;
}
public void setBatteryPercentage(int batteryPercentage) {
this.batteryPercentage = batteryPercentage;
setChanged();
notifyObservers();
}
}
视图了解模型:
public class View implements Observer {
private Model model;
private JTextField txtFldSpeed;
private JTextField txtFldBattery;
private JFrame mainWindow;
public View(Model m) {
this.model = m;
initialize();
}
private void initialize() {
mainWindow = new JFrame();
mainWindow.setTitle("New Window");
mainWindow.setMinimumSize(new Dimension(1280, 720));
mainWindow.setBounds(100, 100, 1280, 720);
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel tPanel1 = new JPanel();
tPanel1.setBorder(new LineBorder(new Color(0, 0, 0)));
tPanel1.setLayout(null);
mainWindow.getContentPane().add(tPanel1);
mainWindow.getContentPane().add(tPanel1);
txtFldSpeed = new JTextField();
txtFldSpeed.setEditable(false);
txtFldSpeed.setBounds(182, 11, 116, 22);
tPanel1.add(txtFldSpeed);
txtFldBattery = new JTextField();
txtFldBattery.setEditable(false);
txtFldBattery.setBounds(182, 43, 116, 22);
tPanel1.add(txtFldBattery);
mainWindow.setVisible(true);
}
@Override
public void update(Observable o, Object arg) {
txtFldSpeed.setText(Float.toString(model.getSpeed()) + " kn");
txtFldBattery.setText(Integer.toString(model.getBatteryPercentage()) + " %");
}
}
控制器将视图添加为模型的观察者:
public class Controller {
private Model model;
private View view;
public Controller(Model m, View v) {
this.model = m;
this.view = v;
}
public void initController() {
model.addObserver(view);
model.setSpeed(10);
}
}
我所期望的是,当模型被更新时,比如说,调用函数setSpeed()
,视图被告知需要在特定字段上更新自己,而不是在每个“可更改”字段上更新自己(如txtFldBattery
)
我之所以要这样做,是因为在视图上,有字段每秒更新几次,而且因为我需要更新视图上的所有内容,一个不需要经常更新的JComboBox
在尝试选择一个选项时会一直关闭
# 1 楼答案
在
update
方法实现中,您可以使用第一个参数o
确定哪个可观察对象发生了更改,使用第二个参数arg
确定调用时哪个值发生了更改:notifyObservers(this.speed);
注意,notifyObservers的签名接受
Object
,并且float
原语不是Object
的子类# 2 楼答案
我将使用SwingPropertyChangeSupport,使模型的每个状态字段都成为“绑定属性”,这样每个状态字段都可以被单独监听
例如,假设你有一个这样的模型:
speed和batteryPercent字段都是“绑定字段”,因为对这些字段的任何更改都将触发property change support对象向已注册到该支持对象的任何侦听器发出通知消息,如
public void setXxxx(...)
方法所示通过这种方式,控制器可以在模型上注册它想要监听的任何属性的侦听器,然后通知视图任何更改。例如:
设置可能看起来像:
旁注:Observable和Observable在最新版本的Java中已被弃用,因此应该避免使用它们