模板方法模式

2018-10-29  本文已影响7人  Whyn

简介

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.
定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

模板方法模式(Template Method Pattern) 实际上是封装了一个固定流程,该流程由几个步骤组成,具体步骤可以由子类进行不同实现,从而让固定的流程产生不同的结果。

模板方法模式 非常简单,其实就是类的继承机制,但它却是一个应用非常广泛的模式。

模板方法模式 本质:抽象封装流程,具体进行实现

主要解决

当完成一个操作具有固定的流程时,由抽象固定流程步骤,具体步骤交给子类进行具体实现(固定的流程,不同的实现)。

优缺点

优点

缺点

使用场景

模式讲解

首先来看下 模板方法模式 的通用 UML 类图:

模板方法模式

从 UML 类图中,我们可以看到,模板方法模式 主要包含两种角色:

以下是 模板方法模式 的通用代码:

class Client {
    public static void main(String[] args) {
        AbstractClass abc = new ConcreteClassA();
        abc.templateMehthod();
        abc = new ConcreteClassB();
        abc.templateMehthod();
    }

    // 抽象模板类
    static abstract class AbstractClass {
        protected void step1() {
            System.out.println("AbstractClass:step1");
        }

        protected void step2() {
            System.out.println("AbstractClass:step2");
        }

        protected void step3() {
            System.out.println("AbstractClass:step3");
        }

        // 声明为final方法,避免子类覆写
        public final void templateMehthod() {
            this.step1();
            this.step2();
            this.step3();
        }
    }

    // 具体实现类A
    static class ConcreteClassA extends AbstractClass {
        @Override
        protected void step1() {
            System.out.println("ConcreateClassA:step1");
        }
    }

    // 具体实现类B
    static class ConcreteClassB extends AbstractClass {
        @Override
        protected void step2() {
            System.out.println("ConcreateClassB:step2");
        }
    }
}

:通常把抽象模板类AbstractClass的模板方法templateMethod定义成final类型,避免子类对其覆写,并遵命定义算法结构/流程的语义。

举个例子

例子:小明要炒两道菜:炒豆芽和炒茄子;
分析:炒菜都有固定步骤:洗菜,热锅下油,下菜翻炒,下调料,起锅。由于炒菜流程是固定的,而其中有些步骤对不同的菜而言具备不同的操作,因此可以很好地使用 模板方法模式 完成炒菜过程。

具体代码如下:

class Client {
    public static void main(String[] args) {
        System.out.println("准备炒豆芽");
        CookVegetable cookVegetable = new CookBeanSprout();
        cookVegetable.cook();

        System.out.println();
        System.out.println("准备炒茄子");
        cookVegetable = new CookEggplant();
        cookVegetable.cook();
    }

    // 抽象模板类:定义炒菜流程
    static abstract class CookVegetable {
        protected void wash() {
            System.out.println("洗菜");
        }

        protected void pourOil() {
            System.out.println("热油下锅");
        }

        protected void fry() {
            System.out.println("下菜翻炒");
        }

        // 具体调料由菜决定
        protected abstract void pourSauce();

        // 具体炒菜流程
        public final void cook() {
            this.wash();
            this.pourOil();
            this.fry();
            this.pourSauce();
            System.out.println("起锅吃菜");
        }
    }

    // 豆芽
    static class CookBeanSprout extends CookVegetable {

        @Override
        protected void pourOil() {
            System.out.println("热锅少油");
        }

        @Override
        protected void fry() {
            System.out.println("快速翻炒");
        }

        @Override
        protected void pourSauce() {
            System.out.println("加盐和少量生抽");
        }
    }

    // 茄子
    static class CookEggplant extends CookVegetable {

        @Override
        protected void wash() {
            System.out.println("去除头尾,然后用水洗下");
        }

        @Override
        protected void pourOil() {
            System.out.println("热锅多油");
        }

        @Override
        protected void pourSauce() {
            System.out.println("加盐和鸡精");
        }
    }
}

结果如下:

准备炒豆芽
洗菜
热锅少油
快速翻炒
加盐和少量生抽
起锅吃菜

准备炒茄子
去除头尾,然后用水洗下
热锅多油
下菜翻炒
加盐和鸡精

我们根据 模板方法模式,就可以抽象定义炒菜的流程,然后针对不同的菜品,由其子类对某些炒菜步骤进行具体实现,这样就完成了炒菜过程。

上一篇下一篇

猜你喜欢

热点阅读