2016-09-24 69 views
3

比方说,我有一个对象Subject其中包括它的观察者的列表和int场:更新fileds的setter中的观察者被认为是不好的做法?

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的场的每一个“设置”操作后,通知所有的人。最常见的代码,我已经知道了执行这样的操作是这样的:

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

但因为我想更新我的每一个新的值设置为state时间我改变一点点代码。

改变notifyAllObservers()访问修饰符私人:

private void notifyAllObservers() { ... code } 

,并增加了新的额外的行到state的二传手:

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

是上面认为是不好的做法的代码?

+2

这看起来好像没什么问题。 –

+1

(错字“观察员列表” - 占有它的?) –

回答

3

为什么不这样好吗?

在我看来,这实际上被认为是一种很好的做法。大概一个月左右之后,你将很有可能忘记拨打notifyAllObservers。或者更糟的是,其他人可能会使用您的代码,并且不知道在设置状态后应该调用notifyAllObservers。如果发生这种情况,您的代码可能无法按预期工作。这就是为什么你应该把notifyAllObservera放在setState方法中。这样,你和其他人不需要担心。

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秒 - 他们怎么知道哪个科目改为状态(考虑Observer.update(Subject who)

  2. 你会怎么做,如果Observer S的一个罚球,而在update?你会停止通知其他人,让异常泡沫?抓住例外,继续通知并重新投掷?(那么如果许多观察者投掷呢?)......决定,决定......

  3. 为什么Observer应该在没有实际状态变化的情况下接收更新?考虑

 public void setState(int state) { 
     if(this.state = state) { 
     this.state = state; 
     notifyAllObservers(); 
     } 
    }
相关问题