观察者模式

订阅者模式通常也成为发布-订阅模式,发布者也称为通知者,订阅者也称为观察者。通知者发出通知,各发布者则收到通知后做出相应的动作。由于存在不同的订阅者和通知者,所以将这两者抽象出来。

其实Subject和Observer是抽象类还是接口,这个是比较灵活的,取决于你的应用场景是怎样,总之就是要将它们抽象出来,方便不同的通知者和观察者来实现它们。

下面是代码实现。

首先是Subject抽象通知者。

 1 package day_9_observer;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 /**
 7  * 抽象通知者类
 8  * @author turbo
 9  *
10  * 2016年9月13日
11  */
12 public abstract class Subject {
13     private List<Observer> observers = new ArrayList<Observer>();
14     private String name;
15     
16     public String getName() {
17         return name;
18     }
19     public void setName(String name) {
20         this.name = name;
21     }
22     public Subject(String name){
23         this.name = name;
24     }
25     /**
26      * 新增观察者
27      * @param observer
28      */
29     public void attach(Observer observer){
30         observers.add(observer);
31     }
32     
33     /**
34      * 移除观察者
35      * @param observer
36      */
37     public void detach(Observer observer){
38         observers.remove(observer);
39     }
40     
41     /**
42      * 通知观察者
43      */
44     public void notifyObservers(){
45         for (Observer observer : observers){
46             observer.update();
47         }
48     }
49 }

接着是抽象观察者。

 1 package day_9_observer;
 2 
 3 /**
 4  * 抽象订阅者
 5  * @author turbo
 6  *
 7  * 2016年9月13日
 8  */
 9 public abstract class Observer {
10     private String name;
11     private Subject subject;
12     
13     public String getName() {
14         return name;
15     }
16 
17     public void setName(String name) {
18         this.name = name;
19     }
20 
21     public Subject getSubject() {
22         return subject;
23     }
24 
25     public void setSubject(Subject subject) {
26         this.subject = subject;
27     }
28 
29     public Observer(String name, Subject subject){
30         this.name = name;
31         this.subject = subject;
32     }
33     
34     public abstract void update();
35 }

下面分别是具体的通知者和订阅者。

 1 package day_9_observer;
 2 
 3 /**
 4  * 具体通知者
 5  * @author turbo
 6  *
 7  * 2016年9月13日
 8  */
 9 public class ConcreteSubject extends Subject {
10     /**
11      * @param name
12      */
13     public ConcreteSubject(String name) {
14         super(name);
15     }
16 
17     private String action;        //这个在本例中并没有什么实际作用
18 
19     public String getAction() {
20         return action;
21     }
22 
23     public void setAction(String action) {
24         this.action = action;
25     }
26     
27 }
 1 package day_9_observer;
 2 
 3 /**
 4  * 具体观察者
 5  * @author turbo
 6  *
 7  * 2016年9月13日
 8  */
 9 public class ConcreteObserver extends Observer {
10     /**
11      * @param name
12      * @param subject
13      */
14     public ConcreteObserver(String name, Subject subject) {
15         super(name, subject);
16     }
17 
18     /* (non-Javadoc)
19      * @see day_9_observer.Observer#update()
20      */
21     @Override
22     public void update() {
23         System.out.println(super.getName() + "收到" + super.getSubject().getName() + "的通知");
24     }
25 
26 }

客户端代码。

 1 package day_9_observer;
 2 
 3 /**
 4  * 客户端
 5  * @author turbo
 6  *
 7  * 2016年9月13日
 8  */
 9 public class Main {
10     
11     public static void main(String[] args){
12         ConcreteSubject concreteSubject = new ConcreteSubject("通知者");
13         ConcreteObserver observer = new ConcreteObserver("订阅者", concreteSubject);
14         
15         concreteSubject.attach(observer);
16         concreteSubject.notifyObservers();
17     }
18 }

输出结果:

这样我们就简单地完成了观察者模式。在《大话设计模式》中提到了,如果观察者是几个风马牛不相及的呢?我们现在是抽象成一个公共类,如果两个观察者无法抽象成一个公共类怎么办呢?《大话设计模式》中提到了利用“事件委托”来实现,由于此书是C#,但在Java中好像并没有线程的事件委托实现,在下一篇中会写利用“事件委托”来实现观察者模式,同样Java自带了Observer接口以提供对观察者模式的支持,下一篇我们也会利用JDK来实现观察者模式。

 

posted @ 2016-09-14 00:20  OKevin  阅读(1018)  评论(0编辑  收藏  举报