一. 前言
观察者模式是非常常见的一种设计模式。其主要用于多个对象需要对同一个对象进行监听的情况,(即多对一)。曾经看过大话设计模式,依稀记得如下这个例子,大意为,曾经员工上班偷懒,被老板看到了,难为情,于是乎,从此之后,当员工偷懒的时候,都会提前给前台小姑娘打个招呼,当老板来的时候,通知下自己,某一天,有三个员工A,B,C偷懒,均给小姑娘打了招呼,当老板来的时候,小姑娘都通知到了,于是老板静静的来,又静静的走了。抽象这个通知的过程,就是典型的观察者模式,简图如下所示:
1. 1 观察者模式原理
观察者模式中基本包含观察者(A,B,C),被观察者(前台小姑娘),时间源(boss来了)。而观察者和被观察者直接的纽带就是回调那一套机制(具体可参考上一篇文档)。通过注册,被观察者保存了各个观察者的回调对象。于是当时间源发生的时候,会把自己的保存的对象统统通知一次。如果任务完成了,观察者解除注册。
二. 案例实现观察者模式
下面我们来实现这个过程,编程语言java,编程软件android studio:1. 监听器,也是回调接口
(接口可以让程序面向抽象,而不面向实际的对象,减小代码的耦合度,可以大大提高程序可扩展性),用于回调发通知。package com.example.test; public interface Listener { void onCallBack(); }
2. 被观察者
主要保存观察者接口对象(注册和解除注册来增加和减少对象),监听时间源,向各个对象发送通知。package com.example.test; import java.util.ArrayList; import java.util.List; public class Secretary { public String name; private List<Listener> liseners = new ArrayList<Listener>(); public Secretary(String str) { name = str; } public void addLisener(Listener lisener) { if (liseners == null) { liseners = new ArrayList<Listener>(); } if (lisener != null) showLog("Add lisener =" + lisener.toString()); liseners.add(lisener); } public void deleteLisener(Listener lisener){ if (liseners == null){ liseners = new ArrayList<Listener>(); } if(lisener != null && liseners.contains(lisener)){ showLog("Delete listener = "+lisener.toString()); liseners.remove(lisener); } } private void showLog(String str){ System.out.println(str); } private void nofifyAll(){ if (liseners.size() < 1){ return; } for(Listener lisener : liseners) { lisener.onCallBack(); } } public void simulateBossComing(){ new Thread(){ @Override public void run() { try{ sleep(3000); }catch(InterruptedException e){ e.printStackTrace(); } nofifyAll(); } }.start(); } }
3. 观察者
主要向被观察者提供监听器(接口的implent对象),并且实现回调接口。观察者A
package com.example.test; public class PersonA { private String name; public PersonA(String str){ name = str; } public Listener getMyListener(){ return new PersonAListeer(); } public class PersonAListeer implements Listener { @Override public void onCallBack() { System.out.println("PersonA, The boss is comming right now!"); } } }
观察者B
package com.example.test; public class PersonB { private String name; public PersonB(String str){ name = str; } public Listener getMyListener(){ return new PersonBListener(); } public class PersonBListener implements Listener { @Override public void onCallBack() { System.out.println("PersonB, The boss is comming right now!"); } } }
4. 测试类
package com.example.test; /** * Task: Two worker, one secretary,one boss * If the boss is comming to the office,found by the secretary and notify the listener. */ public class MyClass { public static void main(String[] args){ PersonA personA = new PersonA("PersonA"); PersonB personB = new PersonB("PersonB"); Secretary secretary = new Secretary("Girl"); secretary.addLisener(personA.getMyListener()); secretary.addLisener(personB.getMyListener()); secretary.simulateBossComing(); } }
5.测试结果:
Add lisener =com.example.test.PersonA$PersonAListeer@75b84c92 Add lisener =com.example.test.PersonB$PersonBListener@6bc7c054 PersonA, The boss is comming right now! PersonB, The boss is comming right now! Process finished with exit code 0