前情提要
上一个小作文中,我们通过接口的形式实现了JAVA的回调函数,做到了一对一的消息通知或者说方法调用,"下载器只需要通知迅雷对象,实际可能会通知多种对象",按照上一节的思路实现一个下载器通知多个对象,下载器需要聚合多个对象,并且还要考虑聚合对象的初始化问题,按照这个思路是不容易实现,一对多的方法调用的。
想要实现一方调用多方的方法该具备怎样的条件?
1.一方应该持有多方的引用
2.多方应该有相同的方法调用入口
普通实现
public class One{
DualA a;
DualB b;
//***省略多方
public initA(DualA a){
this.a = a;
}
public initB(DualB b){
this.b = b;
}
public void toInvokeMethod(){
a.methodA();
b.methodB();
//....
}
public static void main(String[] args){
One one = new One();
one.initA(new A());
//....
one.toInvokeMethod();
}
}
public class DualA {
void methodA(){}
}
public class DualB {
void methodB(){}
}
从上述的代码中可以清晰的看出这些问题:
Q1.如果有更多的多方需要被调用,需要组合更多类
Q2.需要调用太多不同的init方法为引用赋值(不然会空指针)
怎样可以做到调用一个方法解决引用赋值的问题(组合类太多、赋值方法太多)?
所有类都有一个父类Object,可以组合一个Object的集合解决组合类太多问题,赋值方法太多也顺便解决。
public class One{
List<Object> list
void initList(Object o){ //void initA(A a) {this.a = a}
list.add(o);
}
void toInvokeMethod(){
}
}
这个时候toInvokeMthod如何实现?
遍历集合!取出Object对象,会发现没有我们需要调用的方法,使用多态的思想,多方实现一个公共的接口,各自重写里边的调用方法,这样遍历后就可以满足要求。
public interface ObserverInterface {
void update(Object o);
}
public class Observer1 implements ObserverInterface{
@Override
public void update(Object o) {
System.out.println("o1 do something");
}
}
public class Observer2 implements ObserverInterface{
@Override
public void update(Object o) {
System.out.println("o2 do something");
}
}
public class Subject{
List<ObserverInterface> list;
public void addObserver(ObserverInterface o){
list.add(o);
}
public void notify(){
list.foreach(item -> item.update(new Object())) ;//可以传基本数据类型,引用数据类型
}
public static void main(String[] args){
ObserverInterface o1 = new Observer1();
ObserverInterface o2 = new Observer2();
Subject sub = new Subject();
sub.addObserver(o1);
sub.addObserver(o2);
sub.notify();
}
}
可以看出问题,在subject的notify方法调用的update没起到传递有效数据的效果,这些数据只能写死,该如何解决死数据的问题呐?
list.foreach(item -> item.update(new Object()));
list.foreach(item -> item.update(1)) ;
list.foreach(item -> item.update("ABC")) ;
1.让subject这个对象有属性,通过方法为属性赋值,将subject当作参数传递,这样在update时数据就不是死的
public class Subject implements SubjectInterface{
String name;
public Subject(String name){
this.name = name;
}
//....省略相同代码
public boolean notifyObserver() {
if(observers == null){
return false;
}
observers.forEach(item -> item.update(this));
return true;
}
}
public class Observer1 implements ObserverInterface{
public void update(Object o) {
String name = (String) o;
System.out.println("o1 do something" + " name:"+name);
}
}
public static void main(String[] args){
ObserverInterface o1 = new Observer1();
ObserverInterface o2 = new Observer2();
Subject sub = new Subject("zhangsan");
sub.addObserver(o1);
sub.addObserver(o2);
sub.notify();
}
2.构造一个数据对象
public class Data{
String name;
}
void update(Data data){}
void notify(Data data){
observers.forEach(item -> item.update(data));
}
Data d = new Data("zhangsan");
subject.notify(d);//完成调用
类图

思考:用户在系统中刚注册,需要为用户初始化积分和个人设置,该如何实现。
观察者模式实现
1.获取被观察者(主题)
2.获得观察者
3.将观察者和被观察者绑定
4.被观察者(主题)调用通知方法
5.观察者调用方法
public class Main {
public static void main(String[] args) {
RegisteSub concurrentSubject = new RegisteSub();
ObserverInterface pointsObserver = new PointsObserver();
UserObserver userObserver = new UserObserver();
concurrentSubject.addListener(pointsObserver);
concurrentSubject.addListener(userObserver);
RegisterService registerService = new RegisterService();
boolean success = registerService.registerByTel();
if(success){
concurrentSubject.notifyObserver();
}
}
主题和主题接口
public interface SubjectInterface {
boolean addListener(ObserverInterface observer);
boolean removeListener(ObserverInterface observer);
void notifyObserver();
}
public class RegisteSub implements SubjectInterface{
List<ObserverInterface> observers;
@Override
public boolean addListener(ObserverInterface observer) {
if(observers == null){
observers = new ArrayList<>();
}
return observers.add(observer);
}
@Override
public boolean removeListener(ObserverInterface observer) {
if(observers!=null){
return observers.remove(observer);
}
return false;
}
@Override
public void notifyObserver() {
observers.forEach(item -> item.update(this));
}
void registerUserByTel(String tel){
System.out.println(tel + "注册成功");
notifyObserver();
}
}
观察者和观察者接口
public interface ObserverInterface {
void update(Object o);
}
public class PointsObserver implements ObserverInterface{
@Override
public void update(Object o) {
System.out.println("积分系统:初始化!");
}
}
一般实现
public class registeController{
@Override
RegisterService registerService;
@Override
PointsService pointsService;
@Override
UserService userService;
public void regitser(String tel){
boolean success = registerService.registeByTel(tel);//
if(success){ //注册成功,则调用积分服务和个人设置服务的初始化方法
pointsService.init(tel);
userService.init(tel);
}
}
static class RegisterService{
public boolean registerByTel(){
return true;
}
}
}
开发中这样实现功能的代码应该是最为普遍的,假设现在有新需求:当注册成功后,需要初始化用户的好友列表,在上述代码基础上,我们不得不修改类,为其注入新的服务,并修改方法的调用,这样违背了开闭原则。在不使用MQ和违背开闭原则的基础上,我们该如何实现这个需求呐?敬请期待!使用观察者模式的订阅发布模型实现的事务驱动(spring 简版)!
引用博客
https://zhuanlan.zhihu.com/p/431748712 #类图是偷的这个哥们的