标准 专业
多元 极客

设计模式实验室(11)——模板方法模式

什么是模板方法模式?

模板方法模式是一种类行为型模式。

模板方法模式其实就是在不改变代码的情况下,实现了对某些步骤的重定义。

模板方法模式是一个结构比较简单的行为型设计模式,仅仅用到了继承的特性。模板方式将算法流程封装到父类方法中,而在子类中对个算法步骤进行不同的实现,从而实现不同的算法结果。

模板方法模式广泛应用生活中,比如我们常见的点餐系统,具体步骤概括来说就是落位→点餐→上餐→结账。这四个步骤对于每位来就餐的顾客都是相同的,不同的是每个步骤的具体细节,所以我们可以通过模板方法模式实现点餐系统。

核心结构

  • AbstractClass。抽象类,在抽象类中,声明了基本操作方法,基本操作方法可以是具体实现,也可以是抽象的,完全交由子类实现。同时实现了一个总体的算法步骤方法,在步骤方法中对基本方法进行了组合,模板方法不仅可以调用抽象类中实现的基本方法,还可以调用子类的实现的基本方法,亦或是调用其他对象中的方法。
  • ConcreteClass。实现类。继承自抽象类,用于实现或重写在父类中声明的基本方法,来完成具体的算法步骤。

由于目前JDK 8中已经支持接口中实现default方法,也就是我们也可以通过接口的方式作为AbstractClass。

类图展示

模板方法模式

代码分析

由于模板方法模式的简单性,我们将简单的用之实现推送的场景。

首先我们需要定义一个抽象模板类:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/31.
 * 模板方法模式——抽象模板
 */
public abstract class Template {

    /**
     * 调用模板方法
     */
    public void message() {
        title();
        content();
        extraFileds();
        if (isTimingPush()) {
            System.out.println("The message will be sent in the future");
        } else {
            System.out.println("The message is sending");
        }
    }

    public abstract void title();

    public abstract void content();

    public abstract void extraFileds();

    public abstract boolean isTimingPush();

    public abstract boolean isNotification();
}

接着我们根据模板方法模式,定义两种推送场景。

Android推送场景:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/31.
 * 模板方法模式——具体模板
 */
public class AndroidMessagePush extends Template {

    @Override
    public void message() {
        super.message();
    }

    @Override
    public void title() {
        if (isNotification()) {
            System.out.println("Android message's title is building");
        }
    }

    @Override
    public void content() {
        System.out.println("Android message's contents building");
    }

    @Override
    public void extraFileds() {
        System.out.println("Android message's extra fields building");
    }

    @Override
    public boolean isTimingPush() {
        return false;
    }

    @Override
    public boolean isNotification() {
        return false;
    }
}

iOS推送场景:

/**
 * Created by <sunshine> mysunshinedreams@163.com on 2017/1/31.
 * 模板方法模式——具体模板
 */
public class IOSNotificationPush extends Template {

    @Override
    public void message() {
        super.message();
    }

    @Override
    public void title() {
        if (isNotification()) {
            System.out.println("IOS notification;s title building");
        }
    }

    @Override
    public void content() {
        System.out.println("IOS notification's contents building");
    }

    @Override
    public void extraFileds() {
        System.out.println("IOS notification's extra fields building");
    }

    @Override
    public boolean isTimingPush() {
        return true;
    }

    @Override
    public boolean isNotification() {
        return true;
    }
}

模板方法模式就是如此的简单,所以我们需要活学活用。

惯例,测试代码:

/**
 * Created by sunshine on 2017/6/20.
 * 模板方法模式测试
 */
public class TemplateTest {

    public static void main(String[] args) {
        Template androidMessagePush = new AndroidMessagePush();
        androidMessagePush.message();
        Template iOSNotificationPush = new IOSNotificationPush();
        iOSNotificationPush.message();
    }
}

模式总结

优点

  • 代码复用,设计得当的话,大大减少了无用代码。
  • 子类中可以根据钩子判断算法步骤是否执行,提高了系统设计的灵活性。
  • 符合单一职责原则开闭原则。不同的子类可以实现不同的抽象模板。

缺点

  • 如果基于抽象模板的类过多,可能会造成系统的类急剧膨胀。

针对这种情形,我们可以使用结合桥接模式进行复合模式设计。

适用场景

  • 算法步骤基本类似,具体实现略有不同。
  • 代码重构,多个类中的公共代码可以提到父类中完成。
  • 需要通过子类来决定父类算法中的某个步骤是否执行,实现子类对父类的反向控制。
赞(1) 投币

评论 抢沙发

慕勋的实验室慕勋的研究院

码字不容易,路过请投币

支付宝扫一扫

微信扫一扫