设计模式之观察者设计模式

观察者模式定义:

      它是对象的行为模式,它有叫做发布/订阅模式(redis中有这样的概念),模型/视图模式,源/监听器模式或从属模式。它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当这个主题发生改变时,会通知所有他的观察者对象,使之跟随改变更新。

      为什么会有这种设计模式呢?在一个软件生态中,对象之间依赖当一个改变时会有相应的其它对象发生改变。能完成这个问题的方案有很多,但是为了使系统能够易于复用,应选择耦合度较低的方案,减少对象之间的耦合有利于系统的复用,但是同时也应该使这些低耦合对象之间维持行动协调一致,保证高度协作。所以观察者设计模式就出现了。

   它的类图如下图所示:

从类图中可观察到一下几个概念:

       Subject(抽象主题)角色:首先它是一个interface,它维护的一个集合保存所有的观察者,并且提供增加和删除观察者对象和通知所有观察者对象的方法。一般他有被称为Observable(自jdk.1.0 本身库中包含这个类后面会说到)角色,一般用接口或抽象类来表示。

       Observer(抽象观察者)角色:为所有具体观察者定义一个接口,在得到一个主题时通知更新自己,也叫作更新接口。他通常使用接口或抽象类实现。可看到它通常只包含一个方法(update()).

       ConcreteSubject(具体主题)角色:将有关状态存入具体观察者对象,在具体主题发生改变是,给所有登记过的具体观察者发送通知。

      ConcreteObserver(具体观察者)角色:存储与主题状态相关的自状态。

简单实现,代码如下:

   Subject接口:

 

1 package com.obserable;
2 public interface Subject {
3       void addObserver(Observer observer);
4       void delObserver(Observer observer);
5       void notifyall();
6 }

SubjectImpl实现类:

 1 package com.obserable;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Iterator;
 5 import java.util.List;
 6 
 7 public class SubjectImpl implements Subject {
 8       private List<Observer> list = new ArrayList<Observer>();
 9     @Override
10     public void addObserver(Observer observer) {
11         // TODO Auto-generated method stub
12      list.add(observer);
13     }
14 
15     @Override
16     public void delObserver(Observer observer) {
17         // TODO Auto-generated method stub
18   list.remove(observer);
19     }
20 
21     @Override
22     public void notifyall() {
23         Iterator<Observer> iter = list.iterator();
24         while(iter.hasNext()){
25             iter.next().update();
26         }
27     }
28 
29 }

Observer接口:

1 package com.obserable;
2 
3 public interface Observer {
4     void update();
5 }

ObserverImpl实现类:

 1 package com.obserable;
 2 
 3 public class ObserverImpl implements Observer{
 4      private String name;
 5      
 6     public ObserverImpl(String name) {
 7         super();
 8         this.name = name;
 9     }
10 
11     @Override
12     public void update() {
13         System.out.println(name+"I am notify");
14     }
15 
16 }

测试类:

 1 package com.obserable;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         Subject sub = new SubjectImpl();
 6         sub.addObserver(new ObserverImpl("王五"));
 7         sub.addObserver(new ObserverImpl("王五1"));
 8         sub.addObserver(new ObserverImpl("王五2"));
 9         sub.notifyall();
10     }
11 
12 
13 }

结果:

王五I am notify
王五1I am notify
王五2I am notify

还可以使用抽象类来实现Subject,Observer不变;

 1 package com.obserable;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Iterator;
 5 import java.util.List;
 6 
 7 public abstract class AbstractSubjct {
 8 
 9     private List<Observer> list = new ArrayList<Observer>();
10     public void addObserver(Observer observer) {
11    list.add(observer);
12     }
13 
14     public void delObserver(Observer observer) {
15         // TODO Auto-generated method stub
16 list.remove(observer);
17     }
18     public void notifyall() {
19         Iterator<Observer> iter = list.iterator();
20         while(iter.hasNext()){
21             iter.next().update();
22         }
23     }
24 
25 
26 }

抽象类的实现类:

 1 package com.obserable;
 2 
 3 public class JtSubject extends AbstractSubjct{
 4   private String state;
 5   
 6   public void change(String state){
 7       this.state=state;
 8       notifyall();
 9   }
10 }

Observer不变。

测试类:

 1 package com.obserable;
 2 
 3 public class AbsTest {
 4      public static void main(String[] args) {
 5          JtSubject as = new JtSubject();
 6         as.addObserver(new ObserverImpl("王五"));
 7         as.addObserver(new ObserverImpl("王五1"));
 8         as.addObserver(new ObserverImpl("王五2"));
 9         as.change("hello");
10     }
11 }

结果:

王五I am notify
王五1I am notify
王五2I am notify

因为此模式在实际应用中广泛,所以自jdk1.0就纳入的本身库。

Observer接口,等同于上述的Observer,只有一个update方法。

 1  * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved.
 2 package java.util;
 3 
 4 /**
 5  * A class can implement the <code>Observer</code> interface when it
 6  * wants to be informed of changes in observable objects.
 7  *
 8  * @author  Chris Warth
 9  * @see     java.util.Observable
10  * @since   JDK1.0
11  */
12 public interface Observer {
13     /**
14      * This method is called whenever the observed object is changed. An
15      * application calls an <tt>Observable</tt> object's
16      * <code>notifyObservers</code> method to have all the object's
17      * observers notified of the change.
18      *
19      * @param   o     the observable object.
20      * @param   arg   an argument passed to the <code>notifyObservers</code>
21      *                 method.
22      */
23     void update(Observable o, Object arg);
24 }

再看jdk中Observable类,他是一个可实例化类。

 1  * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
 2 
 3 package java.util;
 4 public class Observable {
 5     private boolean changed = false;
 6     private Vector<Observer> obs;
 7 
 8     /** Construct an Observable with zero Observers. */
 9 
10     public Observable() {
11         obs = new Vector<>();
12     }
13 
14   
15     public synchronized void addObserver(Observer o) {
16         if (o == null)
17             throw new NullPointerException();
18         if (!obs.contains(o)) {
19             obs.addElement(o);
20         }
21     }
22 
23   
24     public synchronized void deleteObserver(Observer o) {
25         obs.removeElement(o);
26     }
27 
28   
29     public void notifyObservers() {
30         notifyObservers(null);
31     }
32 
33  
34     public void notifyObservers(Object arg) {
35      
36         Object[] arrLocal;
37 
38         synchronized (this) {
39          
40             if (!changed)
41                 return;
42             arrLocal = obs.toArray();
43             clearChanged();
44         }
45 
46         for (int i = arrLocal.length-1; i>=0; i--)
47             ((Observer)arrLocal[i]).update(this, arg);
48     }
49 
50    
51     public synchronized void deleteObservers() {
52         obs.removeAllElements();
53     }
54 
55     protected synchronized void setChanged() {
56         changed = true;
57     }
58 
59     protected synchronized void clearChanged() {
60         changed = false;
61     }
62 
63     public synchronized boolean hasChanged() {
64         return changed;
65     }
66 
67     public synchronized int countObservers() {
68         return obs.size();
69     }
70 }

可以看到它是线程安全的,方法是有synchronizednchronized修饰的,而且维护的Observer集合使用的Vector。

使用方法和上述一样。

posted @ 2019-12-17 10:51  风中之烛_清  阅读(513)  评论(0编辑  收藏  举报