我们说我有一个对象Subject
,其中包含一个观察者列表和一个int
字段:
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();
}
}
}
我想在每次&#39;之后通知所有人。 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();
}
以上代码是否被视为不良做法?
答案 0 :(得分:3)
为什么这不行?
在我看来,这实际上被认为是一种很好的做法。在一个月左右的时间之后,你很有可能忘记拨打notifyAllObservers
。或者甚至更糟糕的是,其他人可能会使用您的代码并且不知道他们应该在设置状态后调用notifyAllObservers
。如果发生这种情况,您的代码可能无法正常工作。这就是为什么你应该将notifyAllObservera
放在setState
方法中的原因。这样,你和其他人就不用担心了。
答案 1 :(得分: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);
}
}
}
其他值得考虑的事情:
Observer
的 Subject
个实例 - 他们如何知道哪个主题更改了状态(考虑Observer.update(Subject who)
)
如果Observer
中有一个update
在Observer
时抛出,你会怎么做?你会停止通知其他人并让异常泡沫化吗?抓住异常,继续通知并重新抛出?(那么如果许多观察者抛出怎么办?)......决定,决定......
如果没有发生实际状态更改,<TextBox Name="textBox"/>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
myStaticClass.TextBox = textBox;
myStaticClass.Dispatcher = Dispatcher;
}
s应该接收更新的原因是什么?考虑
public void setState(int state) { if(this.state = state) { this.state = state; notifyAllObservers(); } }