观察员设计模式是观察员的行为设计模式之一。观察员设计模式是当你对一个对象的状态感兴趣并希望在发生任何变化时得到通知时有用的。
观察设计模式
According to GoF, observer design pattern intent is;
定义对象之间的一个对多个依赖,以便当一个对象改变状态时,其所有依赖者都被通知并自动更新。
** 主体** 载有观察员名单,以通知其状态的任何变化,因此,它应提供观察员可以登记和自行注销登记的方法。 主题还包含一种将任何变化通知所有观察者的方法,要么在通知观察者的同时发送更新,要么提供另一种获取更新的方法. 观察者应当有一种设置对象来观察的方法,以及另一种被Object用来通知他们任何更新的方法. Java通过_java. 可观察_阶层和_java.util. 观察_界面. 然而,它并没有被广泛使用,因为执行是真正简单的,而且大多数时候我们不希望仅仅为了执行观察者模式而延长一个班级,因为java不会在班级中提供多份遗产. Java Message Service(JMS)使用 ** 观察员设计模式** 连同 [** Mediator type**] (/community/troducers/mediators-design-pattern-java"Java中的Mediator 设计模式-实例教程"),允许应用程序订阅并发布其他应用程序的数据. Model-View-Control(MVC)框架还采用观察者模式,其中Model为主体,观点为可注册的观察员,以便获得对模型的任何更改通知.
观察模式 Java 示例
对于我们的观察员模式Java程序示例,我们将实施一个简单的主题,观察员可以注册这个主题. 每当任何新消息被发布到主题,所有注册表观察员将被通知,他们可以消耗消息。
1package com.journaldev.design.observer;
2
3public interface Subject {
4
5 //methods to register and unregister observers
6 public void register(Observer obj);
7 public void unregister(Observer obj);
8
9 //method to notify observers of change
10 public void notifyObservers();
11
12 //method to get updates from subject
13 public Object getUpdate(Observer obj);
14
15}
接下来,我们将为观察者创建合同,有一个方法将主体附加到观察者身上,另一个方法将被主体用来通知任何变化。
1package com.journaldev.design.observer;
2
3public interface Observer {
4
5 //method to update the observer, used by subject
6 public void update();
7
8 //attach with subject to observe
9 public void setSubject(Subject sub);
10}
现在我们的合同已经准备好了,让我们继续具体落实我们的主题。
1package com.journaldev.design.observer;
2
3import java.util.ArrayList;
4import java.util.List;
5
6public class MyTopic implements Subject {
7
8 private List<Observer> observers;
9 private String message;
10 private boolean changed;
11 private final Object MUTEX= new Object();
12
13 public MyTopic(){
14 this.observers=new ArrayList<>();
15 }
16 @Override
17 public void register(Observer obj) {
18 if(obj == null) throw new NullPointerException("Null Observer");
19 synchronized (MUTEX) {
20 if(!observers.contains(obj)) observers.add(obj);
21 }
22 }
23
24 @Override
25 public void unregister(Observer obj) {
26 synchronized (MUTEX) {
27 observers.remove(obj);
28 }
29 }
30
31 @Override
32 public void notifyObservers() {
33 List<Observer> observersLocal = null;
34 //synchronization is used to make sure any observer registered after message is received is not notified
35 synchronized (MUTEX) {
36 if (!changed)
37 return;
38 observersLocal = new ArrayList<>(this.observers);
39 this.changed=false;
40 }
41 for (Observer obj : observersLocal) {
42 obj.update();
43 }
44
45 }
46
47 @Override
48 public Object getUpdate(Observer obj) {
49 return this.message;
50 }
51
52 //method to post message to the topic
53 public void postMessage(String msg){
54 System.out.println("Message Posted to Topic:"+msg);
55 this.message=msg;
56 this.changed=true;
57 notifyObservers();
58 }
59
60}
注册和删除观察员的方法实施非常简单,额外的方法是 postMessage() 将由客户端应用程序用于将 String 消息发送给主题。 注意布尔变量以跟踪主题状态的变化并在通知观察员中使用。 这种变量是必要的,所以如果没有更新并有人呼叫 notifyObservers() 方法,它不会向观察员发送错误的通知。 也注意使用 [同步](/社区/教程/thread-safety-in-java Java 同步和带示例的线路安全教程
) notifyObservers() 方法,以确保通知只发送给观察员注册在消息发布到主题之前。 这里是观察员的实施,将监视主题。
1package com.journaldev.design.observer;
2
3public class MyTopicSubscriber implements Observer {
4
5 private String name;
6 private Subject topic;
7
8 public MyTopicSubscriber(String nm){
9 this.name=nm;
10 }
11 @Override
12 public void update() {
13 String msg = (String) topic.getUpdate(this);
14 if(msg == null){
15 System.out.println(name+":: No new message");
16 }else
17 System.out.println(name+":: Consuming message::"+msg);
18 }
19
20 @Override
21 public void setSubject(Subject sub) {
22 this.topic=sub;
23 }
24
25}
注意 update() 方法的实施,它正在调用 Subject getUpdate() 方法来获取信息。我们可以通过将消息作为论点传递给 update() 方法来避免此调用。
1package com.journaldev.design.observer;
2
3public class ObserverPatternTest {
4
5 public static void main(String[] args) {
6 //create subject
7 MyTopic topic = new MyTopic();
8
9 //create observers
10 Observer obj1 = new MyTopicSubscriber("Obj1");
11 Observer obj2 = new MyTopicSubscriber("Obj2");
12 Observer obj3 = new MyTopicSubscriber("Obj3");
13
14 //register observers to the subject
15 topic.register(obj1);
16 topic.register(obj2);
17 topic.register(obj3);
18
19 //attach observer to subject
20 obj1.setSubject(topic);
21 obj2.setSubject(topic);
22 obj3.setSubject(topic);
23
24 //check if any update is available
25 obj1.update();
26
27 //now send message to subject
28 topic.postMessage("New Message");
29 }
30
31}
当我们在程序上运行时,我们会跟踪输出。
1Obj1:: No new message
2Message Posted to Topic:New Message
3Obj1:: Consuming message::New Message
4Obj2:: Consuming message::New Message
5Obj3:: Consuming message::New Message
Java Observer 模式类图表
Observer design pattern is also called as publish-subscribe pattern. Some of it's implementations are;
- java.util.EventListener in Swing
- javax.servlet.http.HttpSessionBindingListener
- javax.servlet.http.HttpSessionAttributeListener
这是关于Java的观察者设计模式的全部,我希望你喜欢它,分享你的爱与评论和与他人分享。