zoukankan      html  css  js  c++  java
  • java回调方法、钩子方法以及模板方法模式

    在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类称为回调类,回调类的对象称为回调对象,其处理事件的方法叫做回调方法。(摘自百度百科)

    那么通过上面那句话将百度百科中的“回调函数”翻译成JAVA版:回调方法就是一个通过回调对象的引用(java中的引用存的是对象的地址)调用的方法。如果你把

    回调对象的引用(地址)作参数传递给另一个方法,当这个引用被用来调用其所指向的方法时,我们就说这是回调方法。回调方法不是由该方法的实现方直接调用,
    而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

         

    下面我们来通过一个小需求来实现回调,需求为:王钢蛋去餐厅打饭,餐厅服务员根据其饭量为其打饭。我们先构思下,首先要有个接口,接口中定义个抽象方法为
    饭量(回调接口);其次创建王钢蛋(回调类),让王钢蛋实现这个接口,并想好其饭量(回调方法);最后创建餐厅,餐厅服务员(另一方)接待王钢蛋(回调对
    象)并根据其提供的饭量(回调方法)打饭(特定事件,该事件会调用回调方法)。上代码:

    复制代码
    /**
    * 顾客,去食堂吃饭有个前提,要告诉服务员其饭量,才会给你盛饭
    *
    @author coder

    *
    */
    interface Client{
    /**
    * 告诉服务员其饭量
    *
    @return
    */
    public String appetite();
    }

    class WangGangDan implements Client{

    @Override

    public String appetite() {

    return "一车米饭";

    }

    }

    /

    食堂

    /

    class Restaurant{

    /


    * 打饭方法,前提是客户要告知服务员你的饭量,他会根据你的饭量给你“盛”饭

    *
    @param client 排队的客户

    *
    @return

    */

    public String dozenRice(Client client){

    return "盛了"+client.appetite();

    }

    }

    public class Test1 { //业务处理类,老王去打饭

    public static void main(String[] args) {

    WangGangDan laowang
    =new WangGangDan(); //王钢蛋以别名laowang去食堂要饭

    Restaurant waiter=new Restaurant();

    String dozenRice
    =waiter.dozenRice(laowang);

    System.out.println(dozenRice);
    //最后老王“盛了一车米饭”

    //但是通常我们打饭时不会告诉服务员我们叫什么,这样太麻烦了,那么可不可以只告诉服务员

    //饭量多少就给我们打饭呢?按常理来说我们去餐厅也只会要一次饭。

    //匿名内部类多用来实现回调,简便

    String dozenRice1=waiter.dozenRice(new Client(){

    @Override

    public String appetite() {

    return "一锅米饭";

    }});

    System.out.println(dozenRice1);

    }


    }

    复制代码

             这里将利用模板方法模式来说明钩子方法是什么,许多设计模式都用到了回调,钩子之类的概念,这些基础点理解了,有些模式也就不那么晦涩难懂了,稍微改写下上面的代码就可以:

    复制代码
    /**
    * 模板方法模式:在一个方法中定义一个算法的骨架,而将一些步
    * 骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情
    * 况下,重新定义算法中的某些步骤。
    * 【钩子方法】:原理就是实现为空的方法,在某任务之前、之后、
    * 执行中、报异常后调用的方法(是不是有种熟悉的感觉)。
    * 通常钩子方法是通过抽象类或是本类中的空方法来实现的。
    *
    */
    abstract class Client{
    /**
    * 【模板方法】
    */
    public void templateMethod(){
    before();
    appetite();
    after();
    }
    /**
    * 【钩子方法】在盛饭前(一个空的实现)
    */
    protected void before(){};
    /**
    * 【抽象方法】告诉服务员其饭量
    *
    @return 饭量
    */
    public abstract void appetite();
    /**
    * 【具体方法】盛饭后
    */
    private void after(){
    //实际项目这里是共有的业务逻辑
    System.out.println("拿筷子,找桌子,开吃...");
    }
    }
    /**
    *食堂
    */
    class Restaurant{
    /**
    * 打饭方法,前提是客户要告知服务员你的饭量,他会根据你的饭量给你“盛”饭
    *
    @param client 排队的客户
    *
    @return
    */
    public void dozenRice(Client client){
    client.templateMethod();
    }
    }

    public class Test1 { //业务处理类,老王去打饭
    public static void main(String[] args) {
    Restaurant waiter
    =new Restaurant();
    waiter.dozenRice(
    new Client(){
    @Override
    protected void before() {
    System.out.println(
    "对服务员吹胡子瞪眼!!");
    }
    @Override
    public void appetite() {
    System.out.println(
    "盛了一锅米饭");
    }});

    }
    }
    复制代码

        

  • 相关阅读:
    Android开发-API指南-Manifest介绍
    MSP430G2333下位机乘法运算需要注意的一个问题
    VC++ 6.0使用定时器SetTimer;
    QT编写上位机程序一定要初始化变量以及谨慎操作指针
    QT点击"X"按钮,调用closeEvent()函数来实现调用特定事件(附:粗略介绍QT的信号与槽的使用方法)
    部分LINUX系统由图形界面启动变更为命令行界面启动的方法
    示波器trigger的使用方法
    QT共享库的创建与调用(初级)(附:UI界面不能被改变的其中一个原因)
    随笔:开篇——加入博客园的第N天,变量N无法用char来装载
    c语言课程设计之贪吃蛇代码及思路 c语言课程设计报告之贪吃蛇
  • 原文地址:https://www.cnblogs.com/jpfss/p/9229289.html
Copyright © 2011-2022 走看看