在文件中更新观察者是否被视为不良做法?设置器?

时间:2016-09-24 14:03:15

标签: java design-patterns observer-pattern

我们说我有一个对象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();
}

以上代码是否被视为不良做法?

2 个答案:

答案 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
  1. Subject个实例 - 他们如何知道哪个主题更改了状态(考虑Observer.update(Subject who)

  2. 如果Observer中有一个updateObserver时抛出,你会怎么做?你会停止通知其他人并让异常泡沫化吗?抓住异常,继续通知并重新抛出?(那么如果许多观察者抛出怎么办?)......决定,决定......

  3. 如果没有发生实际状态更改,<TextBox Name="textBox"/> protected override void OnNavigatedTo(NavigationEventArgs e) { myStaticClass.TextBox = textBox; myStaticClass.Dispatcher = Dispatcher; } s应该接收更新的原因是什么?考虑

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