1 问题的提出
在实际业务中,经常会遇到多个对象关注一个对象数据变化的情况。如我在项目中遇到的情况,用户在申请角色单据,在主管签核完成之后需要进行数据的变动,要完成以下功能:向申请用户发送通知邮件,添加用户账户信息,更新最新的用户列表信息给主管。
while(单据签核完成)
{
向申请用户发送通知邮件;
添加用户账户信息;
更新最新的用户列表信息给主管
}
当需要增加数据的变动或删除数据的变动时,需要修改原有的代码,这显然不是我们想看到的情形。观察者模式就可以解决我们遇到的这种问题
观察者模式指当对象的一个状态发生改变时,所有依赖他的对象都必须得到通知并自动更新。可以解决被通知的对象不形成代码耦合的情况,各个被通知的对象之间的关系是一个弱关系,互不干扰.这种设计模式下,有两个非常重要的角色,一个称为“主题”的对象和若干个“观察者”的对象
2 实现的步骤
2.1 定义主题接口
public interface ISubject<T> {
/**
* 注册观察者
* @param observer
* @return
*/
boolean registerObserver(IObserver<T> observer);
/**
* 删除观察者
* @param observer
* @return
*/
boolean unRegisterObserver(IObserver<T> observer);
/**
* 主题通知所有观察者进行数据响应
*/
void notifyObservers();
}
2.1 定义观察者接口与具体的观察者
== 观察者接口==
public interface IObserver<T> {
/**
* 更新数据
* @param data
*/
void refresh(T data);
}
public class PrintObserver<T> implements IObserver<T> {
@Override
public void refresh(T data) {
if(data.getClass()==Integer.class){
System.out.println("整数观察者接收到了数据data"+data);
}else if(data.getClass()==String.class){
System.out.println("字符串观察者接收到了数据data"+data);
}
}
}
public class SavaDataObserver<T> implements IObserver<T> {
@Override
public void refresh(T data) {
if(data.getClass()==Integer.class){
//模拟数据存储
System.out.println("整数观察者存储了数据"+data);
}else if(data.getClass()==String.class){
//模拟数据存储
System.out.println("字符串观察者存储了数据"+data);
}
}
}
在定义观察者接口和主题接口时,采用了泛型数据,因为无法确定观察者更新的数据类型,为了适用用各个类型的topic数据,因此采用泛型数据。当确定观察者观察的对象数据变化的类型时,可不采用泛型的方式
3 测试
public class Main {
public static void main(String[] args) {
Subject subject=new Subject();
//根据notify后的行为的不同区分建立不同的观察者
//打印观察者
IObserver<Integer> observer1=new PrintObserver<>();
//存储观察者
IObserver<Integer> observer2=new SavaDataObserver<>();
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.setData(Integer.valueOf(1));
subject.notifyObservers();
}
}
输出结果如下:
整数观察者接收到了数据data1
整数观察者存储了数据1
== UML类图关系如下==