首先,您需要了解观察者模式。
基本思想是定义一个对象,当它发生变化时通知相关方。 (请注意,观察者模式更通用 - 可观察对象通知观察者有关“某些事件”。对于 MVC,该事件是“发生变化”)
首先你在 OBSERVABLE 和 OBSERVER 之间定义一个契约
package aaa;
// AN OBSERVER INTERFACE
// This is a contract between an interested party (the OBSERVER) and
// the thing it would like to know has changed (the OBSERVABLE)
// The OBSERVABLE will call this method whenever its data changes
public interface SomethingChangedListener {
void somethingChanged(String name, Object newValue);
}
然后你定义 OBSERVABLE
package aaa;
import java.util.ArrayList;
import java.util.List;
// An OBSERVABLE class
public class Person {
// STEP 1: keep track of "who cares"
// outsiders with interest implement the observer interface
// and register with the person to indicate that they care
private List<SomethingChangedListener> listeners = new ArrayList<SomethingChangedListener>();
public void addSomethingChangedListener(SomethingChangedListener scl) {
listeners.add(scl);
}
public void removeSomethingChangedListener(SomethingChangedListener scl) {
listeners.remove(scl);
}
// STEP 2: be able to notify those observers by calling a method in the observer interface
protected void fireSomethingChanged(String name, Object newValue) {
for (SomethingChangedListener scl : listeners) {
scl.somethingChanged(name, newValue);
}
}
// STEP 3: whenever the data changes, notify the observers
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
fireSomethingChanged("age", name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
fireSomethingChanged("name", name);
}
}
这允许任何其他对象“监听”它感兴趣的事物的变化,只要它实现了那个观察者接口。
例如:
package aaa;
public class Test1 {
private static class TestObserver implements SomethingChangedListener {
@Override public void somethingChanged(String name, Object newValue) {
System.out.println("Property '" + name + "' changed to '" + newValue + "'");
}
}
public static void main(String[] args) {
Person p = new Person();
p.addSomethingChangedListener(new TestObserver());
p.setName("Scott");
p.setAge(43);
}
}
创建一个可观察对象(Person)的实例,注册一个观察者(TestObserver),然后与可观察对象交互。运行时,我们看到
Property 'name' changed to 'Scott'
Property 'age' changed to 'Scott'
到目前为止一切顺利。
现在让我们将 Person 称为我们的模型。 MODEL 代表我们想要操作和查看的数据。
我们可以在“用户界面”中执行此操作。用户界面可以是但不限于:
- 图形用户界面 (GUI)
- 命令行界面 (CLI)
- Web 应用程序(HTML、JSP、ASP 等)
- Web 服务(SOAP、REST 等)
每种类型的用户界面 (UI) 的代码可能截然不同,但概念是相同的。
用户界面 (UI) 允许用户(例如一个人或另一台计算机)查看有关模型的信息并对这些信息进行更改。
“视图”是为用户显示信息的 UI 部分。它从模型中读取数据并以某种方式对其进行格式化以呈现它。
如果模型发生变化,则必须更新视图。为此,它将观察者注册到模型中。这些观察者只需在视图中刷新演示文稿的相关部分。
现在如果用户想要进行更改会发生什么?
我们在 UI 中将“控制器”定义为解释用户与该 UI 交互的代码。例如,如果用户在“name”字段中键入,控制器可能会将其解释为“将 'name' 的值更改为用户键入的文本。控制器生成一个
person.setName(textFromField);
调用更新模型。
还记得 setName() 方法的作用吗?它通知观察者这一变化。这将导致 UI 更新其视图。
注意“view”和“controller”不需要是单独的类;它们经常结合在一起。真正需要理解的是“视图”(显示模型数据的 UI 部分)和“控制器”(解释用户交互和更新模型的 UI 部分)的角色。
在某些设置中,例如 Web 应用程序,视图和控制器是非常分离的。控制器解释向服务器发出的 HTTP 请求并更新模式。视图将 HTML 响应呈现给用户。 (如果你在做一个 AJAX 应用程序,设计有点类似于 GUI)
关于 MVC 分离(模型与 UI)的酷点在于,您可以随时在模型中添加或删除 UI,并且可以在同一个模型上拥有多个 UI。如果一个 UI 中的数据发生更改,则所有其他 UI 都会更新以反映更改。
很酷,嗯?