【图解设计模式三】Template Method 模式

将具体处理交给子类

一、知识概述

Template Method 设计模式是指在父类中定义处理流程的框架,在子类中实现具体处理。其主要包含两种主要的角色。

  • AbstractClass: 为抽象类,不仅负责实现模板方法,还负责声明在模板方法中所使用到的抽象方法。
  • ConcreteClass: 为具体类,负责具体实现AbstractClass角色中声明的抽象方法。

二、示例程序

以下为实现了Template Method模式的示例程序,这段示例程序的主要作用是,将字符和字符串循环显示5次,二者分别采用不同的显示格式。

类图示例

程序清单

流程

/**
 * 声明需求方法的抽象类,并使用所声明的方法进行具体处理
 */
public abstract class AbstractDisplay {
    // 方法声明
    public abstract void open();
    public abstract void print();
    public abstract void close();

    // 方法实现
    public final void display() {
        open();
        for (int i = 0; i < 5; i++) {
            print();
        }
        close();
    }
}

/**
 * 测试程序行为的类 将字符和字符串循环显示5次
 */
public class Main {
    public static void main(String[] args) {
        AbstractDisplay d1 = new CharDisplay('H');
        AbstractDisplay d2 = new StringDisplay("Hello, world");
        AbstractDisplay d3 = new StringDisplay("你好,世界");
        d1.display();
        d2.display();
        d3.display();
    }
}

实现

/**
 * 实现了open、print、close方法的类
 */
public class CharDisplay extends AbstractDisplay {
    private char ch;

    public CharDisplay(char ch) {
        this.ch = ch;
    }

    public void open() {
        System.out.print("<<");
    }

    public void print() {
        System.out.print(ch);
    }

    // 这里是方法区的继承,那么实例化之后会是怎么样呢
    public void close() {
        System.out.println(">>");
    }
}

/**
 * 实现了open、print、close方法的类
 */
public class StringDisplay extends AbstractDisplay {
    private String string;
    private int width;

    public StringDisplay(String string) {
        this.string = string;
        this.width = string.getBytes().length;
    }


    public void open() {
        printLine();
    }

    public void print() {
        System.out.println("|" + string + "|");
    }

    public void close() {
        printLine();
    }

    private void printLine() {
        System.out.print("+");
        for (int i = 0; i < width; i++) {
            System.out.print("-");
        }
        System.out.println("+");
    }
}

三、课后习题

问题1:

java.io.InputStream类使用了Template Method 模式,请参考JDK找出其子类需要实现的方法。

回答1:

在子类中需要实现的方法:public abstract in read() throws IOException
该方法会被java.io.InputStream中的模板方法read(byte[] b, int off, int len)循环调用。

问题2:

示例程序中AbstractDisplay的模板方法,使用了修饰符final,why?

回答2:

public是必要的,为了对外提供接口;final虽然非必要,但是其能够限制方法被子类重写(Override),使程序更加的规范化。

问题3:

如果相让抽象类中的open、print、close方法,可以被父子类和同包下的类调用,而不能被其他类调用,需要怎么做?

回答3:

将方法的访问权限由public改成protected

问题4:

Java 当中的接口和抽象类很相似,接口同样也是声明抽象方法的集合。为什么在Template Method模式中,无法使用接口来扮演AbstractClass角色?

回答4:

因为接口只能负责声明抽象方法,而抽象类不仅负责声明抽象方法,还负责具体实现模板方法对抽象方法进行调用,即使用抽象类可以在抽象方法的声明阶段确定调用的流程。
posted @ 2021-02-19 17:27  小z同学  阅读(99)  评论(0编辑  收藏  举报