博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之观察者模式
阅读量:5102 次
发布时间:2019-06-13

本文共 7033 字,大约阅读时间需要 23 分钟。

观察者模式,顾名思义需要两方,一方是被观察的(主题),另一方就是观察者。就拿直播间来说,直播间就相当于一个主题,而用户就是观察者,用户进入直播间就是向主题注册(加进了用户队列),一般来说,用户可以离开直播间(从主题中移除该用户),当然直播间的主播也可以将用户移出直播间(也相当于从主题中移除该用户)。也就是说其实主题和观察者的关系是一对多的关系,主题数据的变化,观察者能及时知道。

下面进行观察者模式的实现,首先是主题接口:

1 package cn.liu.java.myjava.Interface; 2 /** 3  * 这是主题接口,主要作用是注册观察者,移除观察者还有就是通知观察者 4  * 假设这里的应用场景是告知有当前注册的用户,现在有多少个观察者在监听 5  * @author Administrator 6  * 7  */ 8 public interface Subject { 9     //注册观察者10     public void registerObserver(Observer observer);11     //移除观察者12     public void removeObserver(Observer observer);13     //通知所有观察者14     public void notifyObservers();15 }

接下来是观察者接口:

1 package cn.liu.java.myjava.Interface; 2 /** 3  * 观察者接口,该观察者主要是知道当前有多少个观察者注册了(相当于在线场景) 4  * @author Administrator 5  * 6  */ 7 public interface Observer { 8     //观察者被通知时候调用的方法 9     public void show(int num);10     //观察者主动注册11     public void register();12     //观察者主动取消订阅13     public void remove();14 }

接下来是主题接口的具体实现类:

1 package cn.liu.java.myjava; 2  3 import java.util.LinkedList; 4 import java.util.List; 5  6 import cn.liu.java.myjava.Interface.Observer; 7 import cn.liu.java.myjava.Interface.Subject; 8  9 /**10  * 主题的实现类11  * @author Administrator12  *13  */14 public class SubjectImpl implements Subject{15     //主题要通知观察者,那么必须在主题中注册观察者,用一个list来存储观察者。16     //因为linkedlist的实现是使用了链表的实现方式,观察者模式经常需要增删用户,17     //删除用户如果用链表就只需要调整指针,不需要移动后面的元素18     private List
observers = new LinkedList
();19 20 public void registerObserver(Observer observer) {21 // TODO Auto-generated method stub22 observers.add(observer);23 //添加了观察者就通知所有的观察者对象24 notifyObservers();25 }26 27 public void removeObserver(Observer observer) {28 // TODO Auto-generated method stub29 observers.remove(observer);30 notifyObservers();31 }32 33 public void notifyObservers() {34 // TODO Auto-generated method stub35 Observer observer = null;36 for (int i = 0; i < observers.size(); i++) {37 if ((observer = observers.get(i)) != null) {38 observer.show(observers.size());39 }40 }41 }42 43 44 }

最后就是观察者的具体实现:

package cn.liu.java.myjava;import cn.liu.java.myjava.Interface.Observer;import cn.liu.java.myjava.Interface.Subject;/** * 观察者的实现 * @author Administrator * */public class ObserverImpl implements Observer{    //观察者需要保留一个主题的引用,方便观察者的注册和移除    private Subject subject;    //为每个观察者给定一个名字    private String name;    public ObserverImpl(Subject subject , String name) {        this.subject = subject;        this.name = name;    }    public void show(int num) {        // TODO Auto-generated method stub        System.out.println(name+"收到通知:现在有"+num+"人注册了该服务");    }    public void register() {        // TODO Auto-generated method stub        subject.registerObserver(this);    }    public void remove() {        // TODO Auto-generated method stub        subject.removeObserver(this);    }    }

接下来就是测试类:

1 package cn.liu.java.myjava; 2  3 import org.junit.Test; 4  5 import cn.liu.java.myjava.Interface.Observer; 6 import cn.liu.java.myjava.Interface.Subject; 7  8 public class MyTest { 9     @Test10     public void testName() throws Exception {11         Subject subject = new SubjectImpl();12         Observer observer1 = new ObserverImpl(subject , "观察者一");13         Observer observer2 = new ObserverImpl(subject , "观察者二");14         Observer observer3 = new ObserverImpl(subject , "观察者三");15         //观察者主动要求注册(其实其中的内部实现也是通过主题对象来注册)16         subject.registerObserver(observer1);17         //通过主题对象来注册18         observer2.register();19         observer3.register();20         observer2.remove();21         subject.removeObserver(observer3);22         observer1.remove();23         observer1.remove();24     }25 }

测试结果如图:

观察者模式基本实现就是这样了,java类库中也有观察者模式的具体接口,可以直接使用java类库来实现观察者模式,上述例子中不太好的就是由主题来进行各个观察者的通知,其实比较好的就是观察者可以主动到主题中抓取数据,这样可以方便不同的观察者按需来抓取需要的数据,减小主题的复杂性。

下面实现观察者主动去提取主题中的数据(size)

1 package cn.liu.java.myjava.Interface; 2 /** 3  * 这是主题接口,主要作用是注册观察者,移除观察者还有就是通知观察者 4  * 假设这里的应用场景是告知有当前注册的用户,现在有多少个观察者在监听 5  * @author Administrator 6  * 7  */ 8 public interface Subject { 9     //注册观察者10     public void registerObserver(Observer observer);11     //移除观察者12     public void removeObserver(Observer observer);13     //通知所有观察者14     public void notifyObservers();15 }
1 package cn.liu.java.myjava.Interface; 2 /** 3  * 观察者接口,该观察者主要是知道当前有多少个观察者注册了(相当于在线场景) 4  * @author Administrator 5  * 6  */ 7 public interface Observer { 8     //观察者被通知时候调用的方法 9     public void show();10     //观察者主动注册11     public void register();12     //观察者主动取消订阅13     public void remove();14 }
1 package cn.liu.java.myjava; 2  3 import java.util.LinkedList; 4 import java.util.List; 5  6 import cn.liu.java.myjava.Interface.Observer; 7 import cn.liu.java.myjava.Interface.Subject; 8  9 /**10  * 主题的实现类11  * @author Administrator12  *13  */14 public class SubjectImpl implements Subject{15     //主题要通知观察者,那么必须在主题中注册观察者,用一个list来存储观察者。16     //因为linkedlist的实现是使用了链表的实现方式,观察者模式经常需要增删用户,17     //删除用户如果用链表就只需要调整指针,不需要移动后面的元素18     private List
observers = new LinkedList
();19 private int size;20 public void registerObserver(Observer observer) {21 // TODO Auto-generated method stub22 observers.add(observer);23 size = observers.size();24 //添加了观察者就通知所有的观察者对象25 notifyObservers();26 }27 28 public void removeObserver(Observer observer) {29 // TODO Auto-generated method stub30 observers.remove(observer);31 size = observers.size();32 notifyObservers();33 }34 35 public void notifyObservers() {36 // TODO Auto-generated method stub37 Observer observer = null;38 for (int i = 0; i < observers.size(); i++) {39 if ((observer = observers.get(i)) != null) {40 observer.show();41 }42 }43 }44 45 public int getSize() {46 return size;47 }48 49 50 }
1 package cn.liu.java.myjava; 2  3 import cn.liu.java.myjava.Interface.Observer; 4 import cn.liu.java.myjava.Interface.Subject; 5 /** 6  * 观察者的实现 7  * @author Administrator 8  * 9  */10 public class ObserverImpl implements Observer{11     //观察者需要保留一个主题的引用,方便观察者的注册和移除12     private Subject subject;13     //为每个观察者给定一个名字14     private String name;15     public ObserverImpl(Subject subject , String name) {16         this.subject = subject;17         this.name = name;18     }19     public void show() {20         // TODO Auto-generated method stub21         System.out.println(name+"收到通知:现在有"+((SubjectImpl)subject).getSize()+"人注册了该服务");22     }23     public void register() {24         // TODO Auto-generated method stub25         subject.registerObserver(this);26     }27     public void remove() {28         // TODO Auto-generated method stub29         subject.removeObserver(this);30     }31     32 }

测试结果和第一个实现没区别,第二个只是不需要主题传递数据给观察者,观察者直接从主题提取需要的数据。

 

转载于:https://www.cnblogs.com/liucaihao/p/5526450.html

你可能感兴趣的文章
73.fseek与宽字符读取文件
查看>>
git修改远程仓库地址
查看>>
永远的动漫,梦想在,就有远方
查看>>
mysql 查看当前连接及修改连接数
查看>>
springboot No Identifier specified for entity的解决办法
查看>>
【Luogu1303】【模板】A*B Problem
查看>>
慵懒中长大的人,只会挨生活留下的耳光
查看>>
HTML——校友会(bootstrap)
查看>>
【分布计算环境学习笔记】2 分布式系统中的面向对象技术
查看>>
Enable SSH Server
查看>>
宝塔部署项目
查看>>
如何终止线程的运行(C/C++)
查看>>
"远程桌面连接--“发生身份验证错误。要求的函数不受支持
查看>>
【BZOJ1565】 植物大战僵尸
查看>>
视频:"我是设计师"高清完整版Plus拍摄花絮
查看>>
sicp solutions
查看>>
mysql数据库常用命令
查看>>
VALSE2019总结(4)-主题报告
查看>>
浅谈 unix, linux, ios, android 区别和联系
查看>>
PhotoZoom放大图片,真的能无损吗?
查看>>