Java的观察者设计模式
顾名思义,它用于观察一些Objects.Observer手表,用于主题的状态或者属性的任何更改。
将我们对特定对象感兴趣,并且希望在其状态更改时通知,然后我们观察到该对象以及任何州或者何时何时观察到该对象或者属性更改会发生在该对象中,它会通知我们。
如GoF所描述的:"定义对象之间的一对多依赖性,以便当一个对象更改状态时,所有依赖项都会自动通知并更新。
我们可以以两种方式考虑观察者设计模式
- 主题观察者关系:被观察到的对象被归因于观察受试者的主题和类别称为观察者
- Publisher-upercriber关系:发布者是发布数据并将其通知给订阅该发布者的订阅者列表。一个简单的例子是报纸。每当公开发行商发布的新版本时,它将在订阅发布商的订阅者之间分发。
每次观察者都不会监控主题状态是否有任何变化,因为他们将收到主题的每个国家变更,直到他们停止观察主题。
所以它跟随好莱坞原则 - "不要调用给我们,我们会调用给你"。
一些现实生活例子:
我们可能已经浏览了"Flipkart.com-Online Megastore".SO当我们搜索任何产品时,它不可用,那么有选项名为"当产品可用时通知我"。
如果我们订阅该选项,则在产品状态更改时订阅该选项例如:它可用,我们将获得通知邮件"产品现已上载我们可以购买它"。
在这种情况下,产品是主题,我们是观察者。
让我们说,永久地址已更改,我们需要通知Passport权限和PAN卡权限。
因此,这里的护照权限和PAN卡权威是观察员,我们是一个主题。
在Facebook上也,如果我们订阅某人,那么每当新更新发生时,我们都会通知我们。
何时使用它:
- 当一个对象改变其状态时,所有其他依赖性对象必须自动更改其状态以维持一致性
- 当主题不知道它的观察者数量时。
- 当对象应该能够在不知道谁的对象时通知其他对象。
Observer设计模式的UML图:
成分:
主题
- 了解其观察员
- 有任何数量的观察者
- 提供在运行时添加和分离观察者对象的接口
观察者
- 提供更新接口以接收来自主题的信号
concreteSubject.
- 将兴趣状态存储给ConcreteObserver对象。
- 发送通知它的观察者
Concretyobserver
- 保持对CONCRETESUBJECT对象的引用
- 保持与受试者一致的观察者状态。
- 实现更新操作
用于观察者模式的Java内置API:
Java API提供了一个类和一个Inteface,用于实现观察者模式。
java.util.observable-class
java.util.observer-interface
java.util.observable:
对于被观察,程序必须扩展此类。
子类成为可观察到的java.util.observable和其他对象的重写(overwriting)方法可以"观察"该对象状态的更改。
方法:
AddObserver(Observer O):将观察者添加到此主题的观察者列表中。
deleteobserver(Observer O):从观察者列表中删除观察员。
NotifyObservers():如果对象已更改,请通知所有观察者。
哈希():如果对象已更改,则返回true。
setChanged():此方法标记对象已更改
ClaChanganded():此方法指示主题没有更改或者所有观察员已通知。
java.util.observer:
执行"观察"的类必须实现java.util.observer接口。
有一个方法:公共void更新(可观察的obj,对象arg):只要观察到的对象更改,就会调用此方法。
应用程序调用可观察对象的NotifyObServers方法,用于通知所有变革观察者。
例子:
我们可能已经浏览了"Flipkart.com-Online Megastore".SO当我们搜索任何产品时,它不可用,那么有选项名为"当产品可用时通知我"。
如果我们订阅该选项,则在产品状态更改时订阅该选项例如:它可用,我们将获得通知邮件"产品现已上载我们可以购买它"。
Java代码:
下面的接口是我们的主题接口。
它包括添加或者删除观察者的方法,也是在状态变化条件下,通知所有观察者。
1.subject.java:
package org.igi.javapostsforlearning; public interface Subject { public void registerObserver(Observer observer); public void removeObserver(Observer observer); public void notifyObservers(); }
以下类是我们的ConcretEsubject类。
它实现主题接口,从而提供了所有上述三种方法的实现。
2.Product.java:
package org.igi.javapostsforlearning; import java.util.ArrayList; public class Product implements Subject{ private ArrayList observers = new ArrayList(); private String productName; private String productType; String availability; public Product(String productName, String productType,String availability) { super(); this.productName = productName; this.productType = productType; this.availability=availability; } public ArrayList getObservers() { return observers; } public void setObservers(ArrayList observers) { this.observers = observers; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductType() { return productType; } public void setProductType(String productType) { this.productType = productType; } public String getAvailability() { return availability; } public void setAvailability(String availability) { this.availability = availability; notifyObservers(); } public void notifyObservers() { System.out.println("Notifying to all the subscribers when product became available"); for (Observer ob : observers) { ob.update(this.availability ); } } public void registerObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } }
以下接口是我们的观察者接口。
它包括一个名为"更新"的单个方法
3.observer.java:
package org.igi.javapostsforlearning; public interface Observer { public void update(String availability); }
以下类是我们的ConcrriceObserver类。
Implemintsing Observer接口,并提供更新和其他ConcreteObserver特定方法的实现。
4.Person.java:
package org.igi.javapostsforlearning; public class Person implements Observer{ String personName; public Person(String personName) { this.personName = personName; } public String getPersonName() { return personName; } public void setPersonName(String personName) { this.personName = personName; } public void update(String availabiliy) { System.out.println("Hello "+personName+", Product is now "+availabiliy+" on flipkart"); } }
5.observertpatternmain.java:
package org.igi.javapostsforlearning; public class ObserverPatternMain { /** * @Author igi mandliya */ public static void main(String[] args) { Person igiPerson=new Person("igi"); Person johnPerson=new Person("John"); Product samsungMobile=new Product("Samsung", "Mobile", "Not available"); //When you opt for option "Notify me when product is available".Below registerObserver method //get executed samsungMobile.registerObserver(igiPerson); samsungMobile.registerObserver(johnPerson); //Now product is available samsungMobile.setAvailability("Available"); } }
运行:
Notifying to all the subscribers when product became available Hello igi, Product is now Available on flipkart Hello John, Product is now Available on flipkart
现在在上面的程序中,当三星移动变更的可用性时,它会收到已订阅它的预告用户。
使用Java Inbuilt API:
1.Product.java:
package org.igi.javapostsforlearning; import java.util.ArrayList; import java.util.Observable; import java.util.Observer; public class Product extends Observable{ private ArrayList observers = new ArrayList(); private String productName; private String productType; String availability; public Product(String productName, String productType,String availability) { super(); this.productName = productName; this.productType = productType; this.availability=availability; } public ArrayList getObservers() { return observers; } public void setObservers(ArrayList observers) { this.observers = observers; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductType() { return productType; } public void setProductType(String productType) { this.productType = productType; } public String getAvailability() { return availability; } public void setAvailability(String availability) { if(!(this.availability.equalsIgnoreCase(availability))) { this.availability = availability; setChanged(); notifyObservers(this,availability); } } public void notifyObservers(Observable observable,String availability) { System.out.println("Notifying to all the subscribers when product became available"); for (Observer ob : observers) { ob.update(observable,this.availability); } } public void registerObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } }
2.Person.java.
package org.igi.javapostsforlearning; import java.util.Observable; import java.util.Observer; public class Person implements Observer{ String personName; public Person(String personName) { this.personName = personName; } public String getPersonName() { return personName; } public void setPersonName(String personName) { this.personName = personName; } public void update(Observable arg0, Object arg1) { System.out.println("Hello "+personName+", Product is now "+arg1+" on flipkart"); } }
3.observertpatternmain.java:
package org.igi.javapostsforlearning; public class ObserverPatternMain { /** * @Author igi mandliya */ public static void main(String[] args) { Person igiPerson=new Person("igi"); Person johnPerson=new Person("John"); Product samsungMobile=new Product("Samsung", "Mobile", "Not available"); //When you opt for option "Notify me when product is available".Below registerObserver method //get executed samsungMobile.registerObserver(igiPerson); samsungMobile.registerObserver(johnPerson); //Now product is available samsungMobile.setAvailability("Available"); } }
运行:
Notifying to all the subscribers when product became available Hello igi, Product is now Available on flipkart Hello John, Product is now Available on flipkart
关于观察者模式的一些重要点:
- 主题与观察者之间的耦合松散:只有关于其观察者的目的是观察者实现观察者接口。我们可以在不影响主题的情况下注册或者删除任何观察者。
- 支持广播通信:关于主题状态更改的通知不需要指定其接收者。此通知被广播到订阅它的所有感兴趣的对象。
- 这种模式的问题之一是,如果我们有大量订阅者,调试变得非常硬,因为受试者之间隐含的控制流程。
- 虚假更新:如果状态变化的标准没有很好定义,那么有时它会导致虚假更新。