关于回调:

回调是观察者模式以及反应堆模式的基础

一句话,回调就是一种双向调用模式,什么意思呢,就是说,被调用方在被调用时也会调用对方,这就叫回调。“If you call me, i will call back”。
    先看看这个可以说比较经典的使用回调的方式:

背景1:class A 实现接口inA

背景2:class A 中包含一个对于class B的引用b

背景3:class B有一个参数为InA的方法test(InA a)

class A的对象a调用B的方法传入自己(由于形参是个inA a),test(a) ——这一步相当于you call me.

然后b就可以在test方法中调用InA的方法(已经将形参:接口a的引用传入了) ——这一步相当于I call you back.

可以参考下面的代码:

//最基本的回调模式实现:

public interface inA {

public void callBacka();

}

public class A implements inA{

//含有个B的实例

B b=new B();

@Override

public void callBacka() {

// TODO Auto-generated method stub

System.out.println("excute the method in class A");

}

}

public class B {

public void test(inA a){

a.callBacka();

}

public void excuteB(){

System.out.println("excute the method in class B");

}

}

可以看出来,A类可以通过a.b获得b的实例来调用b中的方法,执行完之后,在B类的对应方法中,可以通过传入的A的参数,来实现对于A的方法的回调,这个是很关键的。

回调还可以实现异步操作,比如说,你有一个复杂的问题解决不了,打电话给你的同学,你的同学说可以解决这个问题,但是需要一些时间,那么你不可能一直拿着电话在那里等,你会把你的电话号码告诉他,让他解决之后打电话通知你。回调就是体现在你的同学又反过来拨打你的号码。
    结合到前面所分析的,你打电话给你同学就是【you call me】,你同学解决完之后打电话给你就是回调【i call you back】。

两个关键点:

1、A类中包含一个B的引用,作为其属性

2、B类的需要回去到A的方法中,包含一个方法,这个方法的形参是对于A类的引用。

3、回调方法需要用接口实现,这样A可以通过集成接口,实现不同类型的回调方式。

再总结一下:软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反(注意这个是与之前的的例子相反的),接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。(貌似仅仅是用途不同而已 实质上差不多)同步调用是三者当中最简单的,而回调又常常是异步调用的基础。

观察者模式(Observer)

观察者模相当于是回调模式的扩充。在观察者模式中,观察者相当于上面例子中的A,被观察者相当于上面例子中的B。不同的是有多个观察者,一个被观察者,也可以是多个。

观察者模式的官方定义:

观察者模式定义了对象间的一种一对多依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

当一个被观察者的状态发生改变 所有依赖它的对象都发生变化。

该模式的几个角色:

Subject(被观察的对象接口 ),规定ConcreteSubject的统一接口。

每个Subject可以有多个Observer,(通过在具体实现类中添加观察者引用的ArrayList或者其他类似方式来实现,这是实现回调方式的关键),观察者是先于被观察者创建的,并且要将对于观察者的引用加入到被观察者的ArrayList中,这样才能在被观察者的信息改变了之后通知对应的观察者。(因为观察者是先于被观察者而创建的 而最后要通过被观察者来调用观察者,进行信息的更新,即后创建的,反过来调用先创建的对象,所以是回调)

ConcreteSubject(具体被观察对象)

维护对所有具体观察者的引用的列表,状态发生变化时会发送通知给所有注册的观察者。(通过列表中对于obversor的引用,来是实现回调,更新观察者)

从功能上来讲,ConcreteSubjec至少要包含 addobservor(添加一个观察者) deletobservor(删除一个观察者) 以及updateobservor三个部分,通过updateobservoer来进行回调,对观察者进行更新,或者是通知观察者来执行相对应的事务。

Observer(观察者接口)

规定ConcreteObserver的统一接口;

定义了一个update()方法,在被观察对象状态改变时会被调用。

ConcreteObserver(具体观察者)

维护一个对ConcreteSubject的引用,(这个可以通过对于ConcreteSubject进行引用,以此来调用ConcreteSubject中的方法,比如添加删除之类的操作,这样的话,不用在main函数中生成ConcreteSubject的具体的类了,每一个observer都含有add delete的方法)

特定状态与ConcreteSubject同步,实现Observer接口,通过update()方法接收ConcreteSubject的通知。(回调过来的具体执行部分)

具体分析见下面的代码,将obversor写成了witcher。

//定义观察者接口
public interface iWatcher { public void update(String str); }
//定义被观察者接口
public interface iSubject { public void add(iWatcher w); public void delete(iWatcher w);
//修改观察者类中的信息
public void update(String str); } public class concreteWatcher implements iWatcher { private String str;
private int id; public void setId(int id)
{
this.id=id; }
public int getId(){
return id;
} //构造函数
public concreteWatcher(String str,int id){
this.str=str;
this.id=id;
System.out.println("the str is created:"+str+this.getClass().hashCode());
} @Override
public void update(String str) {
// TODO Auto-generated method stub
this.str=str;
System.out.println(this.getId()+" the str is updated:"+str);
} } public class concreteSubject implements iSubject{ //含有一个观察者的队列 list是观察者队列的引用
ArrayList<iWatcher>list=new ArrayList<iWatcher>();
@Override
public void add(iWatcher w) {
// TODO Auto-generated method stub
list.add(w);
} @Override
public void delete(iWatcher w) {
// TODO Auto-generated method stub
list.remove(w);
} //体现回调的是在这个地方
@Override
public void update(String str) {
// TODO Auto-generated method stub
//由于List是自身类的属性 不用通过方法在去传了
//这里是一个回调 watcher中的方法去进行更新
for(iWatcher w :list){
w.update(str);
}
} } package com.designpatten.Observer; public class Test {
//生成三个观察者
public static void main(String []args){ concreteWatcher a1=new concreteWatcher("watcher1",1);
concreteWatcher a2=new concreteWatcher("watcher2",2);
concreteWatcher a3=new concreteWatcher("watcher3",3); //生成一个被观者 即抽象主题
concreteSubject sub=new concreteSubject();
sub.add(a1);
sub.add(a2);
sub.add(a3); sub.update("update the information"); } }
//执行结果
/*
the str is created:watcher11580958233
the str is created:watcher21580958233
the str is created:watcher31580958233
1 the str is updated:update the information
2 the str is updated:update the information
3 the str is updated:update the information
*/

关于反应堆模式(reactor)

反应器模式(Reactor pattern)与观察者模式(Observer pattern)在这个方面极为相似:当一个主体发生改变时,所有依属体都得到通知。不过,观察者模式与单个事件源关联,而反应器模式则与多个事件源关联 。

Reactor Pattern 是一种为处理服务请求并发提交到一个或者多个服务处理程序的事件设计模式,当请求抵达后,服务处理程序使用多路分配策略,然后同步地派发这些请求至相关的请求处理程序。

Observer patten只是监听一个固定的主题,在reactor patten中,相当于subject的实现实例中同时包含了不同的Aarrylist每个对应一个事件,每一个事件被触发,传到subject中,相对应的Arraylist中引用的类就会被更新(所谓的进行注册过的事件)

在reactor模式中,资料中常常会提到一个Hook Method 即是钩子方法,这个是模板模式的一部分内容,具体的可以参考一下后面列出的链接。

这里就是简单总结一下:

从模板模式的角度来看,方法被分成三类:具体方法,抽象方法,钩子方法。

1、具体方法就是我们平时所写的最常见的最普通的方法。

2、抽象方法在java中就是abstract方法,就是所谓的继承,这个也比较常见。在一个执行过程中几个函数的出现顺序一致,但是每个步骤于在子类中可能有不同的实现,就直接继承,迪对不同的抽象类进行不同的实现即可,这个的核心思想是在父类中提供了一个算法的框架,子类只能遵从这个框架来,但是具体每个步骤的实现上可能有差别。最典型的就是sort函数,每次排序时,可以自定义排序规则,这个可能会设计到具体不同的领域,但是sort函数的整个实现的大的步骤,则是完全固定的。

3、钩子方法其实就是反过来了,利用钩子方法,子类可以一定程度上影响父类的执行流程,钩子方法的返回结果通常为bool型变量,常常将父类中(模板方法)的某一个步骤放在if语句中,如果钩子方法返回true则执行,返回false则不执行。在子类中可以根据实际情况对钩子方法进行覆盖,并对其默认返回值进行修改,从而确定合适的模板方法的执行流程,相当于是子类影响了父类(模板方法)的执行流程。

相关参考资料:

http://blog.csdn.net/pi9nc/article/details/23169357 (  这个感觉比较通俗 )

http://1025250620.iteye.com/blog/1378538

http://daimojingdeyu.iteye.com/blog/828696

http://blog.csdn.net/fengxinze/article/details/7319059(这个是翻译版本)

(肯定是logserver对象先要生成 才能注册到initial dispatcher中 才能进行回调 说实话 对于例子中的get_handler 看得还是有点晕晕乎乎 先记录在这里)

模板方法模式

http://blog.csdn.net/lenotang/article/details/2911246

http://blog.csdn.net/lovelion/article/details/8299927

其他各种网络资料

回调-> 观察者模式->反应堆模式的更多相关文章

  1. 反应堆模式(reactor)

    在提到高性能服务器编程的时候肯定有听过reactor模式,如果只是简单的写一个服务器和客户端建立连接的程序来熟悉一下使用socket函数编程,一般这种情况都是同步方式实现的,服务器阻塞等待客户端的连接 ...

  2. 理解Redis的反应堆模式

    1. Redis的网络模型 Redis基于Reactor模式(反应堆模式)开发了自己的网络模型,形成了一个完备的基于IO复用的事件驱动服务器,但是不由得浮现几个问题: 为什么要使用Reactor模式呢 ...

  3. 反应堆模式最牛的那篇论文--由solidmango执笔翻译

    The Reactor:An Object-Oriented Wrapper for Event-Driven Port Monitoring and Service Demultiplexing 反 ...

  4. JAVA设计模式—观察者模式和Reactor反应堆模式

    被观察者(主题)接口 定义主题对象接口 /**抽象主题角色: 这个主题对象在状态上发生变化时,会通知所有观察者对象 也叫事件对象 */ public interface Subject { //增加一 ...

  5. iOS中常见的设计模式——单例模式\委托模式\观察者模式\MVC模式

    一.单例模式 1. 什么是单例模式? 在iOS应用的生命周期中,某个类只有一个实例. 2. 单例模式解决了什么问题? 想象一下,如果我们要读取文件配置信息,那么每次要读取,我们就要创建一个文件实例,然 ...

  6. Java设计模式(八)观察者模式 迭代器模式

    (十五)观察者模式 观察者模式,定义对象间一对多关系,一个对象状态发生改变,全部依赖于它的对象都收到通知而且自己主动更新,观察者与被观察者分开.比如邮件订阅.RSS订阅,假设有更新就会邮件通知你. i ...

  7. 《Android源码设计模式》--状态模式--责任链模式--解释器模式--命令模式--观察者模式--备忘录模式--迭代器模式

    [状态模式] No1: Wifi设置界面是一个叫做WifiSetting的Fragment实现的 No2: 在不同的状态下对于扫描Wifi这个请求的处理是完全不一样的.在初始状态下扫描请求被直接忽略, ...

  8. NET设计模式 第二部分 行为型模式(18):观察者模式(Observer Pattern)

    概述 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知.如果这样的依赖关系过于紧密,将使软件不能很好地抵御 ...

  9. java观察者模式

      像activeMQ等消息队列中,我们经常会使用发布订阅模式,但是你有没有想过,客户端时如何及时得到订阅的主题的信息?其实就里就用到了观察者模式.在软件系统中,当一个对象的行为依赖于另一个对象的状态 ...

随机推荐

  1. BZOJ 1908. Pku2054 UVA1205 Color a Tree

    传送门 看一眼感觉 $dp$,发现状态没法维护 考虑贪心,然后就想了两个错的贪心... 正解好神啊 首先如果权值最大的点能够一步染色那么肯定要染它 意思就是,一旦父节点被染色那么它就要接着被染色 那么 ...

  2. 详解 HiveUDF 函数

    更多精彩原创内容请关注:JavaInterview,欢迎 star,支持鼓励以下作者,万分感谢. Hive 函数 相信大家对 Hive 都不陌生,那么大家肯定用过 Hive 里面各种各样的函数.可能大 ...

  3. AngularJS语法

    1,$scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带. $scope是一个对象,有可用的方法和属性. $scope可应用在视图和控制器上.2,所有的 ...

  4. Python之路-Python中文件和异常

    一.文件的操作 open函数 在python中,使用open函数,打开一个已经存在的文件,或者新建一个新文件. 函数语法 open(name[, mode[, buffering[,encoding] ...

  5. linux为 rsync 添加开机启动

    [root@rsync-server-1 /]# echo "/usr/bin/rsync --daemon" >> /etc/rc.local [root@rsync ...

  6. Altium Designer设计PCB中如何开槽

    在不同层画槽孔形状实际得到的PCB效果(注意槽孔边缘) 在不同层画槽孔形状进行(注意槽孔边缘) 很多坛友问在使用Altium Designer设计PCB时,想在板子上开一个槽或者挖一个孔该如何操作,是 ...

  7. Java使用多线程发送消息

    在后台管理用户信息的时候,经常会用到批量发送提醒消息,首先想到的有: (1).循环发送列表,逐条发送.优点是:简单,如果发送列表很少,而且没有什么耗时的操作,是比较好的一种选择,缺点是:针对大批量的发 ...

  8. Python---基础---数据类型的内置函数

    2019-05-23 ---------------------------- 一. #数据类型的内置函数Python有哪些数据类型?Number   数值型string   字符型list     ...

  9. 【leetcode】1041. Robot Bounded In Circle

    题目如下: On an infinite plane, a robot initially stands at (0, 0) and faces north.  The robot can recei ...

  10. CSS基础知识总结二

    <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/html"> ...