我正在尝试在 JavaFx 应用程序中实现观察者模式。我从来没有在这里问过一个问题,但这让我有点发疯。
本质上,我试图使用观察者模式来监视解析电话号码文件的类,并在解析文件时自动更新 UI。
在我回答问题之前,这是我的代码:
抽象类 Observer.java
public abstract class Observer
{
public PhoneBook numbers;
public abstract void update();
}
Run Code Online (Sandbox Code Playgroud)
我有一个实现这个的类:
public class PhoneBookObserver extends Observer {
public PhoneBookObserver(PhoneBook numbers)
{
this.numbers = numbers;
this.numbers.attach(this);
}
@Override
public void update()
{
System.out.println(""NUMBER - : " + numbers.GetNumbers());
}
}
Run Code Online (Sandbox Code Playgroud)
在进行解析的课程中,我创建了一个新的 PhoneBookObserver
public PhoneBook ParsePhoneBook()
{
PhoneBook nums= new PhoneBook();
PhoneBookObserver p = new PhoneBookObserver(nums);
// ... Parsing of file - works fine
return nums;
}
Run Code Online (Sandbox Code Playgroud)
目前这会运行并且我的 println from update() 在 PhoneBookObserver 中被输出。
我的问题是:
要直接回答您的问题,我可能会将 实现Observer为控制器中的内部类。然后它可以访问控制器中的所有内容。
假设这里PhoneBook定义了一个形式的方法
public List<PhoneNumber> getPhoneNumbers() ;
Run Code Online (Sandbox Code Playgroud)
那么你可以这样做:
public class Controller {
@FXML
private ListView<PhoneNumber> phoneNumberList ;
private PhoneBook numbers = new PhoneBook() ; // or initialize from elsewhere
public void initialize() {
numbers.attach(new PhoneBookObserver(numbers));
// ...
}
private class PhoneBookObserver extends Observer {
PhoneBookObserver(PhoneBook numbers) {
this.numbers = numbers ;
}
@Override
public void update() {
phoneNumberList.getItems().setAll(numbers.getPhoneNumbers());
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在
public abstract class Observer
{
public PhoneBook numbers;
public abstract void update();
}
Run Code Online (Sandbox Code Playgroud)
该字段numbers实际上没有任何用途,因为唯一的方法不使用它。所以你可以删除它(如果需要,子类可以定义这样的字段)。那么你也可以让它成为一个接口,因为它只有一个方法,它是一个@FunctionalInterface:
@FunctionalInterface
public interface Observer {
public void update() ;
}
Run Code Online (Sandbox Code Playgroud)
现在它可以用 lambda 表达式来实现,所以实现非常简单,你基本上不会遇到“访问 UI”的任何问题:
public class Controller {
@FXML
private ListView<PhoneNumber> phoneNumberList ;
private PhoneBook numbers = new PhoneBook() ; // or initialize from elsewhere
public void initialize() {
numbers.attach(() -> phoneNumberList.getItems().setAll(numbers.getPhoneNumbers());
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
最后,请注意JavaFX 属性和可观察列表基本上已经提供了观察者模式的实现,因此您在这里几乎是在重新发明轮子。你可以有
public class PhoneBook {
private final ObservableList<PhoneNumber> numbers;
public ObservableList<PhoneNumber> getPhoneNumbers() {
return numbers ;
}
}
Run Code Online (Sandbox Code Playgroud)
进而
public class Controller {
@FXML
private ListView<PhoneNumber> phoneNumberList ;
private PhoneBook numbers = new PhoneBook() ; // or initialize from elsewhere
public void initialize() {
phoneNumberList.setItems(numbers.getPhoneNumbers());
}
}
Run Code Online (Sandbox Code Playgroud)
并且列表视图将为您观察(已经观察到的)数字列表。没有真正需要您的Observer或PhoneBookObserver。