首页 > 技术文章 > 观察者模式

huangjialin 2017-11-20 14:58 原文

概念
观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

在项目开发的时候,为了代码的耦合性降低,往往喜欢模块化,模块之间相互独立。那么相应的出现很多问题等待我们解决。比如,有个需求,我从网络下载数据,下载完毕后,有五个页面数据需要更新,当然
随着项目的开发,可能会增加更多的页面,或者去掉一些不必要的页面。再或者说,我在activity中点击某个按钮,传递数据给有若干个页面更新,等等。如果遇到这样的需求,你可能会想到使用广播,EventBus,或者是接口回调等等
我们知道如果一个项目中运用很多的广播,会导致一些古怪的问题出现,比如某些接收不到,数据错乱,等等!今天就和大家使用设计模式来实现这样的需求——观察者模式

先看一张类图:

 

现在简单的实现某一个功能,我在主页面上发送消息,然后另外几个页面接收到数据,并且更新。
先定义一个被观察者接口:

 1 package com.example.observermodetest;
 2 
 3 /**
 4  * Created by Administrator on 2017/11/20 0020.
 5  * 被观察者实现接口
 6  */
 7 
 8 public interface Observerable {
 9     void addObserver(Observer observer);//添加观察者
10 
11     void removeObserver(Observer observer);//移除观察者
12 
13     void notifyObserver(String mes); //通知观察者
14 }

在定义一个观察者接口:

 1 package com.example.observermodetest;
 2 
 3 /**
 4  * Created by Administrator on 2017/11/20 0020.
 5  * 观察者实现接口
 6  */
 7 
 8 public interface Observer {
 9     void tackAaction(String message); //行动接口
10 }

假设有一个土匪(被观察着),警察(观察者)根据土匪而做出的一些反应

土匪:

 1 package com.example.observermodetest;
 2 
 3 import android.app.Activity;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 
 7 import java.util.ArrayList;
 8 import java.util.List;
 9 
10 public class TuFei extends Activity implements Observerable {
11     private List<Observer> observerList = new ArrayList<Observer>();
12 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_tu_fei);
17     }
18 
19     @Override
20     public void addObserver(Observer observer) {
21         observerList.add(observer);
22     }
23 
24     @Override
25     public void removeObserver(Observer observer) {
26         observerList.remove(observer);
27     }
28 
29     @Override
30     public void notifyObserver(String message) {
31         for (Observer ob : observerList) {
32             ob.tackAaction(message);
33         }
34     }
35 }

警察1号:

 1 package com.example.observermodetest;
 2 
 3 import android.app.Activity;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.util.Log;
 7 
 8 /**
 9  * 警察1号
10  */
11 public class PoliceOne extends Activity implements Observer{
12 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_police_one);
17     }
18 
19     @Override
20     public void tackAaction(String message) {
21         Log.d("huangjialin","---------->  我是警察1号"  + message);
22     }
23 }

警察2号:

 1 package com.example.observermodetest;
 2 
 3 import android.app.Activity;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.util.Log;
 7 
 8 /**
 9  * 警察2号
10  */
11 public class PoliceTwo extends Activity implements Observer {
12 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_police_two);
17     }
18 
19     @Override
20     public void tackAaction(String message) {
21         Log.d("huangjialin","---------->  我是警察2号"  + message);
22     }
23 }

警察3号

 1 package com.example.observermodetest;
 2 
 3 import android.app.Activity;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.util.Log;
 7 
 8 /**
 9  * 警察3号
10  */
11 public class PoliceThrid extends Activity implements Observer{
12 
13     @Override
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_police_thrid);
17     }
18 
19     @Override
20     public void tackAaction(String message) {
21         Log.d("huangjialin","---------->  我是警察3号"  + message);
22     }
23 }

关键来了,这里的代码就是把观察者和被观察者关联起来的

 1 package com.example.observermodetest;
 2 
 3 import android.app.Activity;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 
 7 import java.util.ArrayList;
 8 import java.util.List;
 9 
10 /**
11  * 主要的土匪页面
12  */
13 public class MainActivity extends Activity{
14     private List<Observer> observerList = new ArrayList<Observer>();
15 
16     @Override
17     protected void onCreate(Bundle savedInstanceState) {
18         super.onCreate(savedInstanceState);
19         setContentView(R.layout.activity_main);
20 
21         PoliceOne one = new PoliceOne();
22         PoliceTwo two = new PoliceTwo();
23         PoliceThrid thrid = new PoliceThrid();
24 
25         TuFei tuFei = new TuFei();
26         tuFei.addObserver(one);
27         tuFei.addObserver(two);
28         tuFei.addObserver(thrid);
29 
30         tuFei.notifyObserver("杀了他");
31     }
32 
33 }

我们只需要拿到观察者的对象,并且添加进去就好了,如果不需要,则调用removeObserver方法就ok了~~

代码很简单,最后总结一下:

观察者模式的应用场景:
1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
观察者模式的优点:

1、 Subject(被观察者)和Observer(观察者)之间是松偶合的,分别可以各自独立改变。
2、 Subject(被观察者)在发送广播通知的时候,无须指定具体的Observer(观察者),Observer(观察者)可以自己决定是否要订阅Subject(被观察者)的通知。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
观察者模式的缺陷:

1、 松偶合导致代码关系不明显,有时可能难以理解。(废话)
2、 如果一个Subject(被观察者)被大量Observer(观察者)订阅的话,在广播通知的时候可能会有效率问题。(毕竟只是简单的遍历)

 

推荐阅读