设计模式之Template Method模式

       Template Method模式,模板方法模式。顾名思义,其定义就是在父类中定义处理流程的框架,在子类中实现具体的处理方式。先直接上代码,然后我们再来讨论这种模式。现在的大概需求是这样的。
传入一个char型'A',打印如下结果:


输入“Hello World !”打印出如下结果:
设计模式之Template Method模式_第1张图片


在设计模式中我们用到的例子都是一些很简单的例子,主要阐述的是一种思想,然后在自己的项目中用上,为自己带来便利。


       首先来看看思路:先找出需求对我们行为的要求是啥?打印出一些特殊的字符,或者字符串。可以看出来输入的'A'和'Hello World !'都被循环打印了5遍,在打印之前和之后都有别的处理,但是字符和字符串打印之前和打印之后的处理却明显不一样,并且字符串打印的时候,很明显增加了这个玩意儿'|'。那大体的流程就有了,在打印之前调用一个方法open,然后写一个for循环去打印字符和字符串,最后在调用一个close方法作为结束的处理。对应成代码就是下面酱紫的。

      先定义一个基类AbstractDisplay,在该方法中共第一四个方法open,close,print,display。首先open,close,print这三个方法是抽象方法,并未去实现,只是规定了行为。具体怎么做交给子类,自由发挥。display方法则是将子类都要做的流程直接写出来以便子类都能用,不用在每一个子类中都去写重复的代码。

/**
 * Created by PICO-USER Dragon on 2017/3/9.
 */

public abstract class AbstractDisplay {

    protected abstract void open();

    protected abstract void close();

    protected abstract void print();

    public final void display() {

        open();
        for (int i = 0; i < 5; i++) {

            print();
        }
        close();
    }
}
      接着需要先定义一个CharDisplay类继承于AbstractDisplay类,具体实现父类的抽象方法。做自己想要做的动作。

/**
 * Created by PICO-USER on 2017/3/9.
 */

public class CharDisplay extends AbstractDisplay {

    private char charA;

    public CharDisplay(char charA) {

        this.charA = charA;
    }

    @Override
    public void open() {

        System.out.print("<< ");

    }

    @Override
    public void close() {

        System.out.print(" >>\n");

    }

    @Override
    public void print() {

        System.out.print(charA);
    }
}
还有一个StringDisplay子类,跟CharDisplay类大同小异。

/**
 * Created by PICO-USER on 2017/3/9.
 */

public class StringDisplay extends AbstractDisplay {

    private String string;

    public StringDisplay(String string) {

        this.string = string;

    }


    @Override
    public void open() {

        System.out.print("+");
        for (int i = 0; i < 15; i++) {

            System.out.print("-");
        }
        System.out.print("+\n");

    }

    @Override
    public void close() {

        open();

    }

    @Override
    public void print() {

        System.out.print("| " + string + " |\n");

    }
}
最后就是主方法调用了。

 
  
public class TemplateMethod {

    public static void main(String[] args0) {

        AbstractDisplay charDisplay = new CharDisplay('A');
        AbstractDisplay stringDisplay = new StringDisplay("Hello World !");
        charDisplay.display();
        stringDisplay.display();
    }
}
      好了,到这儿代码就完了。开篇已经很清楚的说明了该设计模式的思想,现在我们来说一些细节的东西。

      请注意看display这个方法,这个方法是被final修饰的,为啥用他修饰呢?在里氏替换原则中第一条就是子类可以实现父类的抽象方法,但是不能修改父类的抽象方法,这儿display虽然不是抽象方法,但是他却是子类中公用的一个方法,约定了这种行为,子类就不能对这种行为进行修改,所以用final修饰,不让子类重写该方法。

public final void display()

       再看TemplateMethod类中调用display方法的代码,这儿是用的父类AbstractDisplay来调用,而不是StringDisplay,为什么这么做呢?这是为了保证子类和父类的一致性。即是没有instanceof等指定子类的种类,程序也能正常使用。这就是里氏替换原则中说到的无论在父类型中保存那个子类的实例,程序都能正常的工作。

 
  
AbstractDisplay stringDisplay = new StringDisplay("Hello World !");
                stringDisplay.display();

现在有一个问题:我们能不能用接口去代替AbstractDisplay?答案是:不可以,因为我们这种模式的侧重点在于由父类决定处理流程,这处理流程display方法必须要在父类中去实现,但是接口是不能去实现方法的。

好了到这儿,我们这篇文章就算是完了。那我们Template Method模式的具体有电体现在哪儿呢?
那就是我们不需要在每一个子类中去写display方法的处理流程,这样在以后这个功能出现bug或者需要修改的时候,我们不需要到处找子类去修改,只要修改父类中的这个方法即可。

    

     




你可能感兴趣的:(Java设计模式)