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

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

本文由原创,转载请注明出处:

 

观察者模式简述

观察者模式的使用非常广泛,常用于建立起一种多对一的关系,该模式一定会包含两个角色,观察者和被观察的对象,当被观察的对象发生变化的时候观察者会接受到相应的通知。

 

观察者模式的定义与基本结构

定义:定义一个一对多的依赖关系,当被多个对象依赖的那个对象发生改变的时候,所有依赖它的对象都会得到相应的通知并进行状态的更新。

 

让我们来看一张来自《Head First》的结构图。

Subject:被观察对象的接口,只要实现了这个接口,任何类都可以成为被观察的对象,这种面向接口的编程方式让类之间的耦合度降低。

Observer:观察者对象的接口,只要实现了这个接口,任何类都可以成为被观察的对象,这种面向接口的编程方式让类之间的耦合度降低。

ConcreteSubject:实现了Subject接口的具体实例。

ConcreteObserver:实现了Observer接口的具体实例。

 

注:一对多指的是一个Subject可以被很多observer观察。

 

一个简单的实例(java)

从观察者更新信息的方式上,可以将观察者模式的实现分成两类,一类是每次Subject更新了信息,Observer都会收到更新的信息(被称为push方式),另一类是每次Subject更新的时候,只通知Observer信息被更新了,但是需要Observer在需要的时候自己来取新的信息(被称为pull方式)。

 

我们只给出push方式完整的代码,然后文字叙述pull与push实现的区别,感兴趣的朋友可以自己试着实现pull版本。

 

让我们来考虑这样一个例子,只要我们定了一份新的杂志,每当这份杂志有新的版本的时候,在push方式下,这本杂志就会被送到每一个订阅者的家里,这里发行商就是ConcreteSubject类,顾客是ConcreteObserver类,实现如下。

Subject接口

1 public interface Subject {2     void addObserver(Observer o);3     void deleteObserver(Observer o);4     void notifyObserver();5 }

 

Observer接口

1 public interface Observer {2     void update(String magazine);3 }

 

Publisher类,继承了Subject接口

1 public class Publisher implements Subject { 2     private ArrayList
customer; 3 private String magazine; 4 public Publisher(){ 5 customer=new ArrayList
(); 6 magazine=""; 7 } 8 @Override 9 public void addObserver(Observer o) {10 customer.add(o);11 System.out.println("新顾客加入");12 }13 14 @Override15 public void deleteObserver(Observer o) {16 customer.remove(o);17 System.out.println("老顾客退出");18 }19 @Override20 public void notifyObserver() {21 for(Observer o:customer){22 o.update(magazine);23 }24 }25 public void publishNewMagazine(String magazine){26 this.magazine=magazine;27 notifyObserver();28 }29 }

 

Customer类,继承了Observer接口

1 public class Customer implements Observer { 2     String name; 3     public Customer(String name){ 4         this.name=name; 5     } 6     @Override 7     public void update(String magazine) { 8         System.out.println(name+" 拿到了新的杂志 "+magazine)    ; 9     }10 }

 

测试程序如下

1 public class Test { 2     public static void main(String[] args) { 3         Publisher publisher=new Publisher(); 4         Customer customer1=new Customer("叶良辰"); 5         Customer customer2=new Customer("龙傲天"); 6         publisher.addObserver(customer1); 7         publisher.addObserver(customer2); 8         publisher.publishNewMagazine("装B指南"); 9         publisher.deleteObserver(customer1);10         publisher.publishNewMagazine("上天秘籍");11     }12 }

 

输出如下

 

pull与push主要的区别

1,pull式需要Observer自己去取数据,所以Subject要提供相应的get方法

2,pull式虽然不用主动push数据,但是仍然要在每次更新时告知Observer数据已经更新,所以每一个Observer需要设立一个flag表示自己数据的新旧。

3,object需要判断哪些Observer有权限来取得自己的数据。

pull方式在那种只有最新信息有价值且Subject更新太快而不适合用push的情况下使用比较好,比如手机上接受天气预报信息之类的

 

Java的built-in Observer Pattern

因为观察者模式实在是太常用了,以至于java给我提供了相应的工具直接构建Observer模式,java提供了一个Observable类(作用相当于我们刚刚写的Object,但是这个是类不是接口),和Observer接口,我们只要继承这些类和接口就能直接应用观察者模式了

它们的位置

import java.util.Observable;import java.util.Observer;

 

Observer类里有以下成员方法

addObserver(Observer o);//添加observerclearChanged();//重置更新标志,hasChanged()的返回值将为falsecountObservers();//返回observer的数量deleteObserver(Observer o);//删除一个特定的observerdeleteObservers();//删除所有observerhasChanged();//测试object的内容距上一次通知后有没有更新notifyObservers();//如果object内容有更新,调用这个方法会通知所有observer,之后会调用clearChange()方法,这个方法是为pull式实现准备的。notifyObservers(Object arg);//如果object内容有更新,调用这个方法会将参数中arg的更新推送给所有observer,之后会调用clearChange()方法,这个方法是为push式实现准备的setChanged();//标明object已经更新

 

Observer接口里面只有一个update方法,声明如下

 public void update(Observable o, Object arg); 

第一个参数是被观察的对象,第二个是任何我们想更新给observer的对象,这个对象来自notifyObservers的参数,如果缺失这个参数,表示我们的observer需要自己来拿数据(即pull式实现),如果有这个对象,则属于push式实现。

运用这个java提供的观察者模式的实现我们只需要做两件事。

1,决定使用pull式实现还是push式实现。

2,根据我们的决定实现update方法,如果我们用pull式实现,我们最好在Subject类里提供相应的get方法。

 

这里给出一个示例,还是上面的例子,仍然是push式,这次我们不用写object与observer接口了。

Customer类

1 public class Customer implements Observer { 2     String name; 3     boolean newManagzine=false; 4     public Customer(String name){ 5         this.name=name; 6     } 7     @Override 8     public void update(Observable o, Object arg) { 9             System.out.println(name+" 拿到了新的杂志 "+arg);10     }11 }

 

Publisher类

1 import java.util.Observable; 2 public class Publisher extends Observable { 3     private String magazine; 4     public Publisher(){ 5         super(); 6         magazine=""; 7     } 8     public void publishNewMagazine(String magazine){ 9         setChanged();10         this.magazine=magazine;11         notifyObservers(magazine);12     }13 }

 

test代码完全不用改,输出如下

 

java给的观察者模式的实现方法其实还有有蛮多的局限性的,比如observable是个类而不是接口,而java是不支持多继承的,所以有了局限性,所以大多数情况下,我们还是自己实现会比较方便。

 

观察者模式到此结束♪(^∇^*)

 

参考资料:

1,《Head First 设计模式》

2,在线java API

 

转载于:https://www.cnblogs.com/coffeeSS/p/5481356.html

你可能感兴趣的文章
VUE原理
查看>>
关于Spring Cloud Config服务器介绍
查看>>
Socket通信
查看>>
centos7无网络环境下创建基于scratch镜像的Linux镜像,并带有Java运行环境
查看>>
PostgreSql-psql命令的使用
查看>>
Eclipse Spring框架配置
查看>>
原创:Python编写通讯录,支持模糊查询,利用数据库存储
查看>>
Oracle查询一张表的所有字段
查看>>
Oracle数据库按正则切割字符串
查看>>
关键字
查看>>
保留字(reserved word)
查看>>
标识符(Identifier)
查看>>
Java中的名称命名规范
查看>>
变 量
查看>>
程序流程控制——分支结构
查看>>
运算符
查看>>
数组——基础
查看>>
程序流程控制——循环结构
查看>>
二维数组简单使用
查看>>
面向对象——成员
查看>>