Java观察者设计模式范例

时间:2020-02-23 14:37:12  来源:igfitidea点击:

观察者模式是一种软件设计模式,在这种模式中,一个称为主体的对象维护着依赖它的所有其他对象(主体)的列表。这些家属被称为观察者。如果主题(所有从属对象(观察者)的维护者)的状态发生更改,系统会自动通知它们。通常通过方法调用来完成。

何时使用观察者模式

通常在对象之间存在一对多关系时使用。

当一个对象需要更新时,如果另一个( 相关对象修改/更改其“行为”。

当对象的观察者数量未知时。

如何工作

通常,有一个主题.java一个文件,该文件包含对所有观察者进行添加、删除和更新的所有方法,或者只是初始化它们并在不同的.java文件中执行所有方法功能。按照惯例,还有一个观察者.java文件,其中包含每次主题更改时调用的update()方法。之后,我们必须创建实现Subject类或者Observer类的.java文件。请注意,对于类是实现Subject还是Observer类文件,它会有所不同。

现实生活中的例子

想想你最喜欢的会员服务。也许是健身房,或者是Netflix,或者是完全不同的东西。我们将在这个例子中使用Netflix,但基本上任何其他会员服务都可以。如果Netflix更改了每月会员的价格,而我们正在为此付费,那么它应该通知我们。事实上,它应该通知所有注册/订阅的人他们的服务。

Java观察者设计模式范例

Subject.java

public interface Subject {
  public double getCurrentPrice();
  public void setNewPrice(double newPrice);
  public void addNewSubscriber(Observer newSuObserver);
  public void removeSubscriber(Observer unsubscriber);
  public void notifyAllSubscribers();
}

在主题.java我们将初始化我们将在中使用的方法订阅rabber.java我很快就会介绍给你的文件。这些方法处理添加、删除和每当主题状态更改时触发的消息。

Observer.java

public interface Observer {
  public void update(double price);
}

这是我们的观察课。它有我们将在类中创建的update(double price)方法订阅observer.java文件。请注意:此方法将在每次订阅价格更改时调用。

SubscriptionGrabber.java

import java.util.*;

public class SubscriptionGrabber implements Subject { 
  private List<Observer> subscribers = new ArrayList<Observer>();
  private double price;

  public SubscriptionGrabber() {
      subscribers = new ArrayList<Observer>();
  }

  public double getCurrentPrice() {
      return price;
  }

  public void setNewPrice(double newPrice) {
      this.price = newPrice;
      notifyAllSubscribers();
  }

  public void addNewSubscriber(Observer newSubscriber) {
      subscribers.add(newSubscriber);
  }

  public void removeSubscriber(Observer unsubscriber) {
      int indexOfUnsubscriber = subscribers.indexOf(unsubscriber);
      subscribers.remove(indexOfUnsubscriber);
  }

  public void notifyAllSubscribers() {
      for (Observer subscriber : subscribers){
          subscriber.update(price);
      }
  }
}

java文件使用Subject接口。请注意,在setNewPrice(double newPrice)方法中,我们在设置了新价格之后会通知用户。重要的是,我们要在价格变化后再做,因为如果我们有更多的代码块,这可能会成为一个问题。我们的addSubscriber(Observer newSubscriber)和removeSubscriber(Observer unsubscriber)只是在观察者列表中添加或者删除一个人。我们需要在我们的模式中有一个删除功能,因为我们的目标是只通知订阅者,或者换句话说,只通知使用我们服务的人。我们不需要通知那些不再使用我们服务的人。最后,这个.java文件中的最后一个方法只是在每个订阅服务器上调用update(double price)方法(我们还没有创建这个方法)。

SubscriptionObserver.java

public class SubscriptionObserver implements Observer {
  private double price;
  private Subject subscriberGrabber;
  private int subscriptionID;

  public SubscriptionObserver(Subject subscriptionGrabber) {
      this.subscriberGrabber = subscriptionGrabber;
      this.subscriptionID+=1;
      subscriberGrabber.addNewSubscriber(this);
      System.out.println("New Observer: " + this.subscriptionID);
  }

  public void update(double price) {
      System.out.println("Price changed from $" + this.price + " to $" + price);
      this.price = price;  
  }
}

这是实际上(最终)具有更新功能的.java文件。请注意我是如何其中放入打印语句的。这一点非常重要(在update方法中有一个print语句),因为我们需要直观地显示用户发生了什么。在构造函数方法中,参数总是一个空列表(我们将在下一个.java文件中看到),subscriptionGrabber将是我们的新列表,它将保存订阅服务器。在第9行,我们可以看到我们正在添加这个新的订户。

ObserverPattern.java

public class ObserverPattern {
  public static void main(String[] args) {
      SubscriptionGrabber subscriptionGrabber = new SubscriptionGrabber();
      SubscriptionObserver subscriptionObserver = new SubscriptionObserver(subscriptionGrabber);
      SubscriptionObserver subscriptionObserver2 = new SubscriptionObserver(subscriptionGrabber);
      SubscriptionObserver subscriptionObserver3 = new SubscriptionObserver(subscriptionGrabber);
      subscriptionGrabber.setNewPrice(5);
  }
}

我们在这里创建grabber(列表),然后将该列表作为一个参数传递给subscription observer变量中的构造函数参数。然后我们把订阅的新价格定为5美元。预期的结果将是通知所有用户价格确实已改为5美元。