模板方法模式

/ 设计模式

模板方法模式(Template Method)

定义一个操作算法的骨架,将一些步骤推迟到子类中完成。模板方法使得子类可以不改变一个算法结构即可定义该算法的某些特定步骤

GoF23种设计模式中,属于行为型模式( Behavioral Patterns)

以我们点外卖支付为例。支付时可以选余额宝、招商银行、工商银行支付。虽然不同支付渠道的对接是不一样的,但是支付的流程是统一的。

下单 -> 支付 -> 抽奖 -> 配送

(彩蛋:如果使用余额宝,中奖品质提升)

这里我们就可以用模板方法模式,将下单抽奖配送放入模板中定义好。将支付放入到子类中实现。

实例

模板方法模式总览.png

角色说明

举例

模板方法模式举例

public abstract class AbstractPay {

    protected final void process() {
        order();
        pay();
        if (isAliPay()) {
            System.out.println("中奖品质提升了");
        }
        draw();
        deliver();

    }

    private void order() {
        System.out.println("下单啦");
    }

    abstract void pay();

    //钩子函数
    protected boolean isAliPay() {
        return false;
    }

    private void draw() {
        System.out.println("恭喜你,中奖了");
    }

    private void deliver() {
        System.out.println("配送到家啦,请开门");
    }
}
public class AliPay extends AbstractPay{

    @Override
    void pay() {
        System.out.println("已使用余额宝支付");
    }

    @Override
    protected boolean isAliPay() {
        return true;
    }
}
public class CmbPay extends AbstractPay{
    @Override
    void pay() {
        System.out.println("已使用招商银行支付");
    }
}
public class Client {
    public static void main(String[] args) {
        AbstractPay alipay = new AliPay();
        alipay.process();

        System.out.println("\n又下一单\n");
        AbstractPay cmb = new CmbPay();
        cmb.process();
    }
}
下单啦
已使用余额宝支付
中奖品质提升了
恭喜你,中奖了
配送到家啦,请开门

又下一单

下单啦
已使用招商银行支付
恭喜你,中奖了
配送到家啦,请开门

实例

code:java.lang.ClassLoader

public abstract class ClassLoader {


    //省略...

    //主流程
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

    
    protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        //递归让父类加载该类
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    //用于重写的钩子函数
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        throw new ClassNotFoundException(name);
    }

    //省略...
}

总结

通过模板方法模式,将会很大程度上的提高系统拓展性和代码复用性。如果在设计中遇到有很多共性的处理方式,那么差异性就可以通过模板方法来弥补。