【设计模式系列】模板方法模式

1,764 阅读3分钟

这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

前言

假设我们需要建造一座房子,需要的步骤有:建地基->砌墙->盖房顶。

我们的需求是需要建水泥房,还要建木头房,那么对应的步骤可能需要处理的逻辑不同,但是执行步骤是固定的,那么固定执行的步骤可以作为方法模板定义。

模板方法定义

模板方法是一种行为设计模式。模板方法设计模式用于创建方法执行模板,并将一些实现步骤推迟到子类。

模板方法定义了方法执行的步骤,它可以提供所有或部分子类通用的默认实现。

模板方法超类

我们来完成最前面的例子,建房子需要做的步骤有:建地基、砌墙和盖房顶。重要的一点是,我们不能改变执行顺序,因为我们不能在建地基之前盖房顶嘛。在这种情况下,我们可以创建一个模板方法,使用不同的方法来构建房子。

现在,盖房子的地基对于所有类型的房子都是一样的,无论是木房子还是水泥房子。我们可以提供基本实现,如果子类想重写这个方法也可以,但是多数情况下它对所有类型的房子都是通用的。

/**
 * @author 小黑说Java
 * @ClassName HouseBuildTemplate
 * @Description 修建房屋模板
 * @date 2021/11/14
 **/
public abstract class HouseTemplate {

    // 建房子的模板
    public final void buildHouse() {
        // 1.建地基
        buildFoundation();
        // 2.砌墙
        buildWalls();
        // 3.盖房顶
        buildRoof();
        System.out.println("房子修建完毕。");
    }

    private void buildFoundation() {
        System.out.println("建地基~");
    }

    protected abstract void buildWalls();

    protected abstract void buildRoof() ;
}

为了确保子类不会重写模板方法,应该将buildHouse()其设置为final的。

模板方法实现类

由于我们需要建木头房子和水泥房子,一些方法是需要由子类实现,所以必须将基类设置为抽象类。

木头房

public class WoodHouse extends HouseTemplate {
    @Override
    protected void buildWalls() {
        System.out.println("用木头砌墙");
    }

    @Override
    protected void buildRoof() {
        System.out.println("盖木头房顶");
    }
}

水泥房

/**
 * @author 小黑说Java
 * @ClassName CementHouse
 * @Description 水泥房
 * @date 2021/11/14
 **/
public class CementHouse extends HouseTemplate {
    @Override
    protected void buildWalls() {
        System.out.println("修水泥墙~");
    }

    @Override
    protected void buildRoof() {
        System.out.println("盖水泥房顶");
    }
}

模板方法客户端

让我们用一个测试程序来测试模板方法模式示例。

/**
 * @author 小黑说Java
 * @ClassName TemplateMethodTest
 * @date 2021/11/14
 **/
public class TemplateMethodTest {
    public static void main(String[] args) {
        // 使用模板方法
        WoodHouse woodHouse = new WoodHouse();
        woodHouse.buildHouse();
        System.out.println("-----------------");
        CementHouse cementHouse = new CementHouse();
        cementHouse.buildHouse();
    }
}

注意,客户端正在调用基类的模板方法,根据不同步骤的实现,它使用了来自基类的一些方法和来自子类的一些方法。

运行结果:

模板方法类图

JDK中的模板方法模式

  • java.io.InputStream,java.io.OutputStream,java.io.Reader,java.io.Writer中的非抽象方法。
  • java.util.AbstractList,java.util.AbstractSet,java.util.AbstractMap中的非抽象方法。

模板方法设计模式要点

  1. 模板方法由固定的步骤组成,模板方法应该是final的,对于某些步骤,基类和子类的实现可以是不同的;
  2. 大多数时候,子类调用父类中的方法,但在模板方法模式中,超类模板方法调用子类中的方法;
  3. 基类的默认实现方法称为hooks,他们是为了被子类覆盖,如果你想要一些不覆盖的方法,可以将方法修饰为final。

以上就是模板方法模式的全部内容,如果对你有帮助,点个赞吧!