《设计模式》之五:模板方法模式

模板方法模式 Template Method Pattern 定义如下:

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm‘s structure

先定义抽象模板类:

/**
 * 抽象模板类
 * 为了防止恶心操作,模板方法都会加上final关键字,不允许覆盖
 *
 * @author XiongNeng
 * @version 1.0
 * @since 13-5-22
 */
public abstract class AbstractTemplate {
    // 基本方法
    protected abstract void doSomething();
    // 基本方法
    protected abstract void doAnything();
    // 模板方法
    public final void templateMethod() {
        // 调用基本方法,完成相关的业务逻辑
        this.doSomething();
        this.doAnything();
    }
}

 然后是实现类:

public class ConcreteClass1 extends AbstractTemplate {
    @Override
    protected void doSomething() {
        System.out.println("class1 doSomething...");
    }

    @Override
    protected void doAnything() {
        System.out.println("class1 doAnything...");
    }
}
public class ConcreteClass2 extends AbstractTemplate {
    @Override
    protected void doSomething() {
        System.out.println("class2 doSomething...");
    }

    @Override
    protected void doAnything() {
        System.out.println("class2 doAnything...");
    }
}

注意:

抽象模板中的基本方法尽量设计为protected,符合迪米特法则,不需要暴露的属性或方法尽量不要设置为protected,更不要设置为public。实现类若非必要,尽量不要扩大父类中的访问权限。

模板方法的优点:

1,封装不变部分,扩展可变部分

2,提取公共部分代码,便于维护

3,抽象父类负责控制行为,而具体子类负责实现行为,相当于一个司令负责调度下面的部署作战方案,具体怎样去执行这个命令达到目的(到底是夜袭还是埋伏还是奇袭),就是下属决定的了。

模板方法的缺点:

抽象类定义了部分抽象方法,由子类实现,子类执行结果影响了父类结果,也就是子类对父类产生了影响,这在负责项目中,会给代码阅读带来一定的难度,让新手感到不适。

模板方法使用场景:

1,多个子类有公有方法,并且逻辑基本相同

2,重要、负责的算法,可以把核心算法设计为模板方法,周边的相关细节功能由子类实现

3,重构时候,模板方法是一个经常使用的模式,把相同代码抽取到父类中,然后通过钩子函数(见 模板方法模式的扩展)约束其行为

模板方法的扩展:

public abstract class AbstractTemplate {
    // 基本方法
    protected abstract void doSomething();
    // 基本方法
    protected abstract void doAnything();
    // 模板方法
    public final void templateMethod() {
        // 调用基本方法,完成相关的业务逻辑
        this.doSomething();
        this.doAnything();
        if (hookFlag()) {
            System.out.println("----Oh yes, hookFlag...");
        } else {
            System.out.println("----Oh no, hookFlag...");
        }
    }

    // 钩子方法
    protected abstract boolean hookFlag();
}
public class ConcreteClass1 extends AbstractTemplate {
    private boolean hookFlag;
    @Override
    protected void doSomething() {
        System.out.println("class1 doSomething...");
    }

    @Override
    protected void doAnything() {
        System.out.println("class1 doAnything...");
    }

    @Override
    protected boolean hookFlag() {
        return hookFlag;
    }

    public void setHookFlag(boolean hookFlag) {
        this.hookFlag = hookFlag;
    }
}

 外界条件的改变可以影响到模板方法的执行。我们抽象类中hookFlag()方法返回值影响了模板方法执行结果,该方法叫钩子方法。有了钩子方法模板方法才算完美。

最佳实践:

父类建立框架,子类在重写了父类部分的方法后,再调用从父类继承的方法,也就是模板方法,产生不同的结果,而这正是模板方法模式。这也可以理解为父类调用了子类的方法,你修改了子类,影响了父类的行为,曲线救国的方式实现了父类依赖子类的场景,模板方法就是这种效果。

模板方法在一些开源框架中应用非常多,它提供了一个抽象类,然后开源框架写了一堆子类。

如果你需要扩展功能,可以继承这个抽象类,然后覆写protected方法,在然后就是调用一个类似于execute的模板方法,就完成了你的扩展开放,非常容易扩展的一种模式。

本人博客已搬家,新地址为:http://yidao620c.github.io/

猜你喜欢

转载自yidao620c.iteye.com/blog/1873704