首页 > 代码库 > 观察者模式

观察者模式

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

技术分享

其实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 observer28      */29     public void attach(Observer observer){30         observers.add(observer);31     }32     33     /**34      * 移除观察者35      * @param observer36      */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 name12      */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 name12      * @param subject13      */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     @Override22     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来实现观察者模式。

 

观察者模式