2016-09-24 14 views
3

だが、私はそのオブザーバーのリストで構成されたオブジェクトSubjectintフィールドがあるとしましょう:filedsの設定者のオブザーバーを更新するのは悪い習慣と考えられますか?

package example.template.pattern.observer; 

import java.util.ArrayList; 
import java.util.List; 

public class Subject { 

    private List<Observer> observers = new ArrayList<Observer>(); 
    private int state; 

    public int getState() { 
     return state; 
    } 

    public void setState(int state) { 
     this.state = state; 
    } 

    public void attach(Observer observer) { 
     observers.add(observer); 
    } 

    public void notifyAllObservers() { 
     for (Observer observer : observers) { 
      observer.update(); 
     } 
    } 
} 

私はstateのフィールドのすべての「設定」操作後にそれらのすべてを通知したいと思います。私はstateに新しい値を設定するたびに、私は少しのコードを変更し、更新したいので

Subject subject = new Subject(); 
subject.add(newObserver); 
subject.setState(newState); 
subject.notifyAllObservers(); 

しかし:このような操作を行うために、私が知っている最も一般的なコードは次のようなものです。

は民間へnotifyAllObservers()アクセス修飾子変更:

private void notifyAllObservers() { ... code } 

をそしてstateのセッターに新しい余分な行を追加しました:

public void setState(int state) { 
    this.state = state; 
    notifyAllObservers(); 
} 

は、上記の悪い習慣とみなさコードですか?

+2

考えてみましょう。 –

+1

(typo "オブザーバーのリスト" - 所有物?) –

答えて

3

なぜこれは問題ありませんか?

私の意見では、これは実際には良い方法と考えられます。 1ヶ月程度後にnotifyAllObserversに電話することを忘れる可能性が非常に高くなります。さらに悪いことに、他の人が自分のコードを使用している可能性があり、状態を設定した後にnotifyAllObserversに電話する必要があるかどうかわかりません。この場合、コードが期待どおりに機能しない可能性があります。そのため、メソッドにnotifyAllObserveraを入れる必要があります。このようにして、あなたと他の人々はそれについて心配する必要はありません。

3

それは、罰金だが、注意して続行

-

Observerの一つは、通知を受信した結果として、自分自身を削除することを決定した場合は? (はい、私は知っている、掲示コードがdetachObserverを示すが、稀に、このメソッドを逃すことは良いアイデアではありませんしません)

ので、仮定の下で一つが、その後、そこにある:

class SatisfiedObserver { 
    Subject observed; 

    public SatisfiedObserver(Subject subject) { 
    this.observed=subject; 
    subject.attach(this); 
    } 

    public void update() { 
    // Doing some work 
    // Well, I'm satisfied 
    this.observed.detach(this); 
    // Now, innocent as it looks, **THIS** will blow 
    // the for cycle in Subject.notifyAllObservers() with a 
    // ConcurrentModificationException 
    } 
} 

ソリューション:検討する価値

public void notifyAllObservers() { 
    Observer[] obses=this.observersArray(); 
    for (Observer observer : obses) { 
     observer.update(); 
    } 
} 

protected final Observer[] observersArray() { 
    Observer[] retval=new Observer[0]; 
    synchronized(this.observers) { 
    // we don't want other threads to screw up observers while we take a copy 
    // And since we don't want that, we'll nee to synchronize the attach 
    // and detach as well: its not like the observers will 
    // attach/detach all the time to fear serious 
    // performance impact 
    retval=this.observers.toArray(retval); 
    } 
    return retval; 
} 

public void attach(Observer o) { 
    if(null!=o) { 
    synchronized(this.observers) { 
     this.observers.add(o); 
    } 
    } 
} 
public void detach(Observer o) { 
    if(null!=o) { 
    synchronized(this.observers) { 
     this.observers.remove(o); 
    } 
    } 
} 

他のもの:

  1. Observerのインスタンスは、複数のSubject Sに登録 - それらがどのように状態を変更した主題を知っています(Observer.update(Subject who)を考える)

  2. updateにおけるながらObserver Sのいずれかがスローした場合、あなたが何をしますか?あなたは他の人に知らせるのをやめて、例外をバブルさせますか?例外をキャッチし、通知を続行し、再起動しますか?(多くのオブザーバーが投げた場合はどうなりますか?)決定、決定...

  3. Observerは実際の状態の変更が発生していない場合に更新を受け取る必要がありますか?これは私には正常に見える

 public void setState(int state) { 
     if(this.state = state) { 
     this.state = state; 
     notifyAllObservers(); 
     } 
    }
関連する問題