回调方法、模板方法模式、钩子(hook)区分

其实这三者之间没什么可区分的,因为他们是不同领域的概念。但是他们非常相似都是在抽象的定义了方法,然后子类实现它。他们都是java多态特性的实践。

概念领域区分:

1.正确的说应该就是模板方法模式,模板方法模式提供模板方法,这个方法是一个模板算法,或者说在方法的调用顺序上固定了一个模板。
2.回调方法,是固定一个方法外观,java中通过接口实现。
3.钩子方法,是一个抽象类提供空实现,子类进行选择性重写的方法。钩子方法也出现在模板方法模式中。

区分

其实就是主要是模板方法模式和回调模式的区分。简单来说就是模板方法模式使用的是抽象类,既然要定义算法逻辑,那么就一定需要一个实现算法的方法

模板方法模式与钩子方法

详见《head first设计模式》第8章——模板方法模式。
模板方法模式使用抽象类来定义方法调用的逻辑。子类继承抽象类,从而获取到了这个逻辑,然后提供某些具体方法实现。

abstract class AbstractClass{
    /*
    *模板方法,提供一种模板算法或者说在方法的调用顺序上固定了一个模板。
    */
    final void templateMenthod(){
        primitiveOperation1();
        primitiveOperation2();
        if(hookOperation()){
            concreteOperation();
        }
    }
    abstract void primitiveOperation1();
    abstract void primitiveOperation2();
    void concreteOperation(){
        //抽象类提供了某些实现
    }
    boolean hookOperation(){
        return true;//钩子方法,子类可以实现这个方法,也可以不
    }
}
class ConcreteClass1 extends AbstractClass{
    @override
    void primitiveOperation1(){
        System.out.println("con 1.1");
    }
    @override
    void primitiveOperation2(){
        System.out.println("con 1.2");
    }
    /*
    *重写了钩子方法,重置了判断逻辑
    */
    @override
    boolean hookOperation(){
        if(getUserInput().toLowerCase().startsWith("y")){
        return true;
        }else{
            return false;
        }
    }
    private String getUserInput(){
        String answer = null;
        BufferedReader in = new BufferedReader (new InputStream(System.in));
        try{
            answer = in.readline;
        }catch (IOException e){
        }
        if (answer == null){
         return "no";
        }
        return answer;
    }
}

上面提供了一个子类实现了某些方法实现,最终使templateMenthod()这个方法能够正常运行。

class ConcreteClass2 extends AbstractClass{
    @override
    void primitiveOperation1(){
        System.out.println("con 2.1");
    }
    @override
    void primitiveOperation2(){
        System.out.println("con 2.2");
    }
}
public class Test{
    public static void main(String[] args){
        ConcreteClass1 c1 = new ConcreteClass1();
        ConcreteClass2 c2 = new ConcreteClass2();
        c1.templateMenthod();
        c2.templateMenthod();
    }
}

AbstractClass定义了逻辑,子类提供了实现,这种设计模式解耦了算法逻辑与具体实现,完成了算法的代码复用。而钩子方法给子类在一定程度上更改原先的逻辑,提供了一定的灵活性。

回调方法

之前写过一篇理解java中回调机制的文章,具体可以看一看。
其实在C语言和js中都可以直接传递函数引用(要正确理解回调可以先看一下js回调函数的示例),而java中是没有这一语法特性的 。那么我们想要完成回调就需要传递一个对象,然后在调用这个对象特定方法,通过接口我们约定方法的参数、返回值、方法名这些要素,使用的时候把具体的接口实现传递过去,就实现了方法的回调。
可见回调用到的是接口,而不是模板方法模式里面的抽象类。

总结

回调方法和模板方法使用了抽象方法,
回调利用的接口,由于java中不具备传递函数指针这一语法特性,于是利用接口来实现方法回调。它注重的是对方法的描述——方法名是什么、方法参数有什么、返回值如何。
模板方法模式利用抽象类,注重都是由父类来控制算法逻辑,子类提供具体每个算法步骤的实现。
钩子方法其实就是普通的抽象类多态,它在模板方法模式中提供了改变原始逻辑的空间。

你可能感兴趣的:(java,设计模式,java,设计模式)