2017-03-02 11 views
0

JavaFxアプリケーションでObserverパターンを実装しようとしています。私はここで質問したことは一度もありませんが、これは私を少し狂ってしまいます。JavafxとObserverパターン - UIの更新

私はObserverパターンを使用して、電話番号のファイルを解析しているクラスを監視し、ファイルが解析されると自動的にUIを更新しようとしています。私は私の質問に入る前に

、ここに私のコードは次のとおりです。

抽象クラスObserver.java

public abstract class Observer 
{ 
    public PhoneBook numbers; 

    public abstract void update(); 
} 

私はこれを実装するクラスがあります。では

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()); 

    } 
} 

を私は新しいPhoneBookObserverを作成しました。

public PhoneBook ParsePhoneBook() 
{ 
    PhoneBook nums= new PhoneBook(); 
    PhoneBookObserver p = new PhoneBookObserver(nums); 

    // ... Parsing of file - works fine 

    return nums; 
} 

現在、これが実行され、PhoneBookObserverのupdate()からのprintlnが出力されます。

私の質問は以下のとおりです。

  • PhoneBookObserverの更新方法は、私のために私のUIを更新することはできますか?コントローラのJavaFx要素にはどのようにアクセスしますか?
  • コントローラをオブザーバにし、update()をオーバーライドしてコントローラでUI要素を更新できますか?それは悪いですか?
+0

[JavaFXプロパティ](http://docs.oracle.com/javase/8/javafx/properties-binding-tutorial/binding.htm#JFXBD107)は基本的にすでにオブザーバパターンを実装しています。なぜそれらを使用して、車輪を改革するのを避けてはいけませんか? –

+0

リスナーはどこに追加しますか?初期化で? –

+0

通常、はいです。どのように設定するかによって異なりますが、ほとんどのシナリオではこれが明らかです。 –

答えて

1

あなたの質問に直接答えるには、コントローラの内部クラスとしてObserverを実装すると思います。その後、コントローラ内のすべてにアクセスできます。ここPhoneBookを想定し

は、あなたができる形式

public List<PhoneNumber> getPhoneNumbers() ; 

の方法を定義します。

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()); 
     } 
    } 
} 

注意を

public abstract class Observer 
{ 
    public PhoneBook numbers; 

    public abstract void update(); 
} 

にフィールドnumbersが本当に何の目的を果たしていないこと、唯一の方法はそれを使用しないからです。だからあなたはそれを削除することができます(サブクラスは必要ならばそのようなフィールドを定義することができます)。そして、あなたは同様にそれインターフェースことがあり、それが唯一の方法を持っているので、それは@FunctionalInterfaceです:

@FunctionalInterface 
public interface Observer { 
    public void update() ; 
} 

と今ではラムダ式で実現することができるので、実装はあなたが基本的に停止することを非常に薄いです「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()); 
     // ... 
    } 

} 

、あなたはかなりここで車輪の再発明しているのでJavaFX Propertiesと観測可能なリストは、基本的にはすでに、オブザーバーパターンの実装を提供することに注意してください。あなただけの

public class PhoneBook { 

    private final ObservableList<PhoneNumber> numbers; 

    public ObservableList<PhoneNumber> getPhoneNumbers() { 
     return numbers ; 
    } 
} 

、その後

public class Controller { 

    @FXML 
    private ListView<PhoneNumber> phoneNumberList ; 

    private PhoneBook numbers = new PhoneBook() ; // or initialize from elsewhere 

    public void initialize() { 
     phoneNumberList.setItems(numbers.getPhoneNumbers()); 
    } 

} 

を持っている可能性があり、リストビューには、あなたのための数字の(既に観測可能)リストを遵守します。 ObserverまたはPhoneBookObserverの実際の必要はありません。

+0

これを試してみますが、initializeメソッドでnumbers.attach(new PhoneBookObserver());でPhoneBookオブジェクトを渡す必要はありませんか? –

+0

はい、申し訳ありませんが、それを修正しました。 (私はすでにこれが冗長であるという考え方にしていました:) –

+0

これを試してみましたが、PhoneBookObserverのupdate()メソッドは決して起動されません。出力されないprintlnも追加しました。 –