回调思想和钩子函数的区别

来源:互联网 发布:java链表的实现 编辑:程序博客网 时间:2024/06/05 04:52
浅谈对java callback 以及 “钩子”的理解
1、首先,callback和“钩子”是两个完全不同的概念:
callback是指:由我们自己实现的,但是预留给系统调用的函数,我们自己是没有机会调用的,但是我们知道系统在什么情况下会调用该方法。
“钩子”是指:声明在抽象类中的方法,只有空的或默认的实现,通常应用在模板设计模式中,让子类可以对算法的不同点进行选择或挂钩,要不要挂钩由子类决定。


2、在这里,我主要介绍callback,顺道分析了一下何为“钩子”。那么什么是回调函数呢?我认为,回调函数就是预留给系统调用的函数,而且我们往往知道该函数被调用的时机。这里有两点需要注意:
第一点,我们写回调函数不是给自己调用的,而是准备给系统在将来某一时刻调用的;
第二点,我们应该知道系统在什么情形下会调用我们写的回调函数。

一句话,回调是一种双向调用模式,什么意思呢,就是说,被调用方在被调用时也会调用对方,这就叫回调。“If you call me, i will call back”。 
不理解?没关系,先看看这个可以说比较经典的使用回调的方式: 
class A实现接口InA ——背景1
class A中包含一个class B的引用b ——背景2
class B有一个参数为InA的方法test(InA a) ——背景3
A的对象a调用B的方法传入自己,test(a) ——这一步相当于you call me
然后b就可以在test方法中调用InA的方法 ——这一步相当于i call you back


经典代码:

//相当于接口InA  public interface BoomWTC{    //获得拉登的决定    public benLaDengDecide();      // 执行轰炸世贸    public void boom();  }    //相当于class A  public class At$911 implements BoomWTC{//相当于【背景1】    private boolean decide;    private TerroristAttack ta;//相当于【背景2】      public At$911(){      Date now=new Date();      SimpleDateFormat myFmt1=new SimpleDateFormat("yy/MM/dd HH:mm");      this.dicede= myFmt.format(dt).equals("01/09/11 09:44");      this.ta=new TerroristAttack();    }      //获得拉登的决定    public boolean benLaDengDecide(){      return decide;    }      // 执行轰炸世贸    public void boom(){      ta.attack(new At$911);//class A调用class B的方法传入自己的对象,相当于【you call me】    }  }    //相当于class B  public class TerroristAttack{    public TerroristAttack(){    }      public attack(BoomWTC bmw){//这相当于【背景3】      if(bmw.benLaDengDecide()){//class B在方法中回调class A的方法,相当于【i call you back】       //let's go.........      }    }  } 


钩子函数经典代码:

1,模板类

package com.pattern.template;    public abstract class CaffeineBeverageWithHook {            void prepareRecipe(){          boilWater();          brew();          pourInCup();          if(customerWantsCondiments()){              addCondiments();          }      }        abstract void brew();            abstract void addCondiments();            void boilWater(){          System.out.println("Boiling water");      }            void pourInCup(){          System.out.println("Pouring into cup");      }            boolean customerWantsCondiments(){          return true;      }    }  


2,模板的子类实现类
package com.pattern.template;    import java.io.BufferedReader;  import java.io.IOException;  import java.io.InputStreamReader;      public class CoffeeWithHook extends CaffeineBeverageWithHook{        /**        * @see com.pattern.template.CaffeineBeverageWithHook#brew()       */      @Override      void brew() {          System.out.println("Dripping Coffee through filter");      }        /**        * @see com.pattern.template.CaffeineBeverageWithHook#addCondiments()       */      @Override      void addCondiments() {          System.out.println("Adding Sugar and Milk");      }            public boolean customerWantsCondiments(){          String answer = getUserInput();                    if(answer.toLowerCase().startsWith("y")){              return true;          } else{              return false;          }      }            private String getUserInput(){          String answer = null;          System.out.println("Would you like milk and sugar with your coffee (y/n)?");                    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));                    try {              answer = in.readLine();          } catch (IOException e) {              System.out.println("IO Exception!");          }                    if(answer == null){              return "no";          }          return answer;      }    } 

3,测试类

package com.pattern.template;    public class BeverageTestDrive {            public static void main(String[] args) {            CoffeeWithHook coffeeHook = new CoffeeWithHook();          System.out.println("\nMaking tea...");          coffeeHook.prepareRecipe();      }  }

4,输出结果:
Making tea...
Boiling water
Dripping Coffee through filter
Pouring into cup
Would you like milk and sugar with your coffee (y/n)?
y
Adding Sugar and Milk

0 0
原创粉丝点击