Template Method: 从李渊开国看模板方法模式

假如史书记载没有水分的话,那么相对于其他开国皇帝,李渊的难度最低,毕竟什么事情都交给他儿子干就完事了。

从晋阳起兵,李渊父子用了七年时间,先后消灭薛举父子、李轨、宋金刚、刘武周、王世充、窦建德、萧铣、杜伏威和梁师都等割据势力。

其中薛举父子、宋金刚、刘武周、王世充、窦建德、杜伏威(招降)、梁师都都是被李世民击败的。

那么我们把李渊开国用Java代码描述就是:

abstract class 李渊{
    abstract void 消灭薛举父子();
    abstract void 消灭李轨();
    abstract void 消灭宋金刚();
    abstract void 消灭刘武周();
    abstract void 消灭王世充();
    abstract void 消灭窦建德();
    void 消灭萧铣(){
        System.out.println("消灭了萧铣");
    }
    abstract void 召降杜伏威();
    abstract void 消灭梁师都();
}

然后你可以看到,除了消灭萧铣,我把其他方法都写成了抽象方法,因为我们知道这些事都不是李渊自己直接做的。

那么李渊想建立唐朝的话,他只需要一个个调用方法就行了

abstract class 李渊{
    abstract void 消灭薛举父子();
    abstract void 消灭李轨();
    abstract void 消灭宋金刚();
    abstract void 消灭刘武周();
    abstract void 消灭王世充();
    abstract void 消灭窦建德();
    void 消灭萧铣(){
        System.out.println("消灭了萧铣");
    }
    abstract void 召降杜伏威();
    abstract void 消灭梁师都();

    public void 建立唐朝(){
        消灭薛举父子();
        消灭李轨();
        消灭宋金刚();
        消灭刘武周();
        消灭王世充();
        消灭窦建德();
        消灭萧铣();
        召降杜伏威();
        消灭梁师都();
        System.out.println("李唐建立了");
    }
}

简单的来说就是这样的。但是真的想开国的话,不能只有抽象方法啊,还必须一步一步的真正的实现上面的方法,这时候李世民就来了。李世民作为李渊的儿子,直接继承父类就行了。

class 李世民 extends 李渊{
    @Override
    void 消灭薛举父子() {
        System.out.println("消灭薛举父子");
    }

    @Override
    void 消灭李轨() {
        System.out.println("消灭李轨");
    }

    @Override
    void 消灭宋金刚() {
        System.out.println("消灭宋金刚");
    }

    @Override
    void 消灭刘武周() {
        System.out.println("消灭刘武周");
    }

    @Override
    void 消灭王世充() {
        System.out.println("消灭王世充");
    }

    @Override
    void 消灭窦建德() {
        System.out.println("消灭窦建德");
    }

    @Override
    void 召降杜伏威() {
        System.out.println("召降杜伏威");
    }

    @Override
    void 消灭梁师都() {
        System.out.println("消灭梁师都");
    }
}

我们的李世民类实现了李渊没有实现的方法。

然后我们来测试下建立唐朝

public class Test {
    public static void main(String[] args) {
        李渊 liYuan = new 李世民();
        liYuan.建立唐朝();
    }
}

李渊 liYuan = new 李世民();这个语句逻辑上看着有点怪异啊,不过意思就是这个意思吧。

作为父类的李渊,给出了统一天下的整体战略,而具体实施的细节就是交给子类来,让我们的代码依赖于抽象而不是具体的实现,这是软件工程中的经典做法。

假如另一个时空,没有李世民,那么李渊也可以让其他子女替他完成各个战略,比如这样的

class 平阳公主 extends 李渊{
    @Override
    void 消灭薛举父子() {
        System.out.println("平阳公主了消灭薛举父子");
    }
    // ...
}


public class Test {
    public static void main(String[] args) {
        李渊 liYuan = new 平阳公主();
        liYuan.建立唐朝();
    }
}

模板方法的核心在于为了完成一件事情(比如建立唐朝),很有可能需要做大量的事情。

但是如果让一个类包含实现这个目的所用到所有的细节,会让代码很臃肿。我们把抽象和实现分离。李渊作为总指挥官,负责全局战略上的全局调度,但是不负责细节的实现。而李世民则接受李渊的调遣,负责实现各个细节。

模板方法模式是抽象与实践分离的又一个经典实践。

原文发布于github

https://github.com/fish-stack...


fishBugs
40 声望2 粉丝