Javafx 和观察者模式 - 更新 UI

tim*_*ins 2 javafx

我正在尝试在 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 中被输出。

我的问题是:

  • PhoneBookObserver 的更新方法可以为我更新我的 UI 吗?它如何访问我的控制器中的 JavaFx 元素?
  • 我可以让我的控制器成为观察者,覆盖 update() 并使用它从我的控制器中更新我的 UI 元素吗?那不好吗?

Jam*_*s_D 5

要直接回答您的问题,我可能会将 实现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)

并且列表视图将为您观察(已经观察到的)数字列表。没有真正需要您的ObserverPhoneBookObserver