这是我参与新手入门的第2篇文章。
前言
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。同时呢RxJava是基于观察者模式的一种编程模型想要学RxJava首先是需要对观察者模式有一定的了解。
观察者模式介绍
“牵一发而动全身”当一个对象发生改变,其他已登记在案的对象观察到这一改变时做出相应的措施。通过这种方式来达到减少依赖关系,解除耦合。
观察者模式的定义
定义对象间的一种一对多的以来关系,是的每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
优点:
- 观察者和被观察者之间是抽象耦合。
- 增强系统灵活性、可扩展性。
缺点:
- 我们的程序一般包括一个被观察者,多个观察者。在Java中消息的通知是默认是顺序执行的,一个观察者卡顿会导致系统整体的响应时间延迟。这种情况下,可以考虑使用异步的方式。
观察者UML图
ISubject: 抽象主题,也就是被观察者的角色(Observable),它将所有观察者对象的引用保存到容器里,每个主题都可以包含任意数量的观察者,抽象主题提供一个接口,可以增加,删除观察者对象。
ConcreteSubject: 具体主题,在其内部状态发生改变时,给所有注册者发出通知。
ConcreteObserver: 具体的观察者拥有实际的职责,该角色实现观察者所定义的更新接口,以便于在CncreteSubject的状态发生改变时,更新自身状态。
代码实现
实现场景: 张三和李四通过天气预报观察天气,是否要下雨或者是刮风。
被观察者(ConcreteSubject)推送给观察者(Observer)
- 首先定义Subject主题接口即被观察者。
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer... observer);
void notifyObservers(boolean isRain, boolean isWindy);
}
复制代码
- 定义观察者超类
public interface Observer {
void update(boolean isRain, boolean isWindy);
}
复制代码
- 天气数据,实际被观察者。实现接口方法,持有一个存放Observer的集合。
public class WeatherData implements Subject {
private ArrayList<Observer> observerList;
public WeatherData() {
this.observerList = new ArrayList<>();
}
/***
* 注册观察者
* @param observer 观察者
*/
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
/***
* 移除观察者
* @param Observer...observer Java 5开始,Java语言对方法参数支持一种新写法,叫可变长度参数列表,
* 其语法就是类型后跟“…”表示此处接受的参数为0到多个Object类型的对象,或者是一个Object[]
*/
@Override
public void removeObserver(Observer... observer) {
if(observer.length == 0){
observerList.removeAll(observerList);
}else {
for (Observer observers : observer) {
observerList.remove(observers);
}
}
System.out.println("observerList size is " + observerList.size());
}
/**
* 通知所有观察者数据改变
* @param isRain
* @param isWindy
*/
@Override
public void notifyObservers(boolean isRain, boolean isWindy) {
for (Observer observer : observerList) {
observer.update(isRain, isWindy);
}
}
public void onChange(boolean isRain, boolean isWindy){
notifyObservers(isRain, isWindy);
}
}
复制代码
- 定义实体类和工具类
public class User implements Observer {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void update(boolean isRain, boolean isWindy) {
String name = getName();
System.out.println("notify " + name + " isRain -> " + isRain + ", isWindy -> " + isWindy );
switch (getName()){
case "Zhangsan":
//做自己要做的事情
break;
case "Lisi":
//TODO
break;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return age == user.age && Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
复制代码
public abstract class SingletonUtils<T> {
private T instance;
public abstract T create();
public final T getInstance(){
if(Objects.isNull(instance)){
synchronized (this){
if(Objects.isNull(instance)) instance = create();
}
}
return instance;
}
}
复制代码
- 定义客户端
public class Client {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
weatherData.registerObserver(new SingletonUtils<User>() {
@Override
public User create() {
User user = new User();
user.setName("Zhangsan");
return user;
}
}.getInstance());
weatherData.registerObserver(new SingletonUtils<User>() {
@Override
public User create() {
User user = new User();
user.setName("Lisi");
return user;
}
}.getInstance());
weatherData.onChange(true,false);
weatherData.removeObserver();
}
}
复制代码
输出:使用完记得将存放Observer的容器清空。
由观察者(Observer)主动去拉数据
- 天气数据,实际被观察者。实现Observer(使用JDK提供的工具类,java.util.Observable)接口方法。
import java.util.Observable;
import java.util.Observer;
public class WeatherDatas extends Observable {
boolean isRain;
boolean isWindy;
public WeatherDatas() {
}
public boolean getRain() {
return isRain;
}
public boolean getWindy() {
return isWindy;
}
@Override
public synchronized void addObserver(Observer o) {
super.addObserver(o);
}
@Override
public void notifyObservers() {
super.notifyObservers();
}
@Override
protected synchronized void setChanged() {
super.setChanged();
}
public void onChange(boolean isRain, boolean isWindy){
this.isRain = isRain;
this.isWindy = isWindy;
//一定要先调用setChanged,notifyObservers中对changed变量做了判断。
setChanged();
notifyObservers();
}
}
复制代码
- 定义观察者子类,实现java.util.Observer
import java.util.Observable;
import java.util.Observer;
public class Users implements Observer {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void update(Observable o, Object arg) {
if(o instanceof WeatherDatas){
WeatherDatas weatherDatas = (WeatherDatas) o;
System.out.println("notify " + name + " isRain -> " + weatherDatas.getRain() +
", isWindy -> " + weatherDatas.getWindy());
switch (getName()){
case "Zhangsan":
//TODO
break;
case "Lisi":
//TODO
break;
}
}
}
}
复制代码
在通知所有观察者前一定要先调用setChange,源码中可以看到,如果change为false,会直接return,不在通知各观察者。
结尾
像ListView常用的Adapter.notifityDataSetChanged,RxJava中观察者模式都是必不可少的,灵活性强,耦合性低并且是Android源码中优秀运用的典范。针不错,今天有学到了一个设计模式。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END