Blog

Blog

PHODAL

设计模式实战: Template Method(模板方法)

设计模式实战: Template Method(模板方法)

原本对于设计模式的写作还不在当前的计划中,然而因为在写TWU作业的时候,觉得代码写得不好,于是慢慢试着一点点重构,重新看着设计模式。也开始记录这一点点的方法,至少这些步骤是必要的。

Main函数

从基本的App说起

对于一个基本的C/C++/Java/Python的Application来说,他只需要有一个Main函数就够了。对于一个好一点的APP来说,他可能是下面的步骤,

main(){
    init();
    while(!condition()){
        do();
    }
}

上面的代码是我在学51/AVR等各式嵌入式设备时,经常是按上面的写法写的,对于一个更符合人性的App来说他应该会有一个退出函数。

main(){
    init();
    while(!condition()){
        do();
    }
    exit();
}

于是很幸运地我找到了这样的一个例子。

过去看过Arduino的代码,了解过他是如何工作的,对于一个Arduino的代码来说,必要的两个函数就是。

void setup() {
}

void loop() {
}

setup()函数相当于上面的init(),而loop()函数刚相当于上面的do()。似乎这就是我们想要的东西,看看Arduino目录中的Arduino.h就会发现,如下的代码(删减部分代码)

#include <Arduino.h>

int main(void)
{
    init();
    setup();        
    for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }

    return 0;
}

代码中的for(;;)看上去似乎比while(True)容易理解得多,这也就是为什么嵌入式中经常用到的是for(;;),从某种意义上来说两者是等价的。再有不同的地方,就是gcc规定了,main()函数不能是void。so,两者是差不多的。只是没有,并没有在上面看到模板方法,等等。我们在上面所做的事情,便是创建一个框架。

Template Method

模板方法: 在一方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

对于我来说,我就是在基本的App中遇到的情况是一样的,在我的例子中,一开始我的代码是这样写的。

public static void main(String[] args) throws IOException {
    initLibrary();
    while(!isQuit){
        loop();
    }
    exit;
}

protected void initLibrary(); {
    System.out.println(welcomeMessage);
}

protected void loop() {
    String key = "";
    Scanner sc = new Scanner(System.in);
    key = sc.nextLine();

    System.out.println(results);
    if(key.equals("Quit")){
        setQuit();
    }
}

protected void exit() {
    System.out.println("Quit Library");
}

只是这样写感觉很是别扭,看上去一点高大上的感觉,也木有。于是,打开书,找找灵感,就在《敏捷软件开发》一书中找到了类似的案例。Template Method模式可以分离能用的算法和具体的上下文,而我们通用的算法便是。

main(){
    init();
    while(!condition()){
        do();
    }
    exit();
}

看上去正好似乎我们当前的案例,于是便照猫画虎地来了一遍。

Template Method实战

创建了一个名为App的抽象基类,

public abstract class App {
    private boolean isQuit = false;

    protected abstract void loop();
    protected abstract void exit();

    private boolean quit() {
        return isQuit;
    }

    protected boolean setQuit() {
        return isQuit = true;
    }

    protected abstract void init();

    public void run(){
        init();
        while(!quit()){
            loop();
        }
        exit();
    }
}

而这个也和书中的一样,是一个通用的主循环应用程序。从应用的run函数中,可以看到主循环。而所有的工作也都交付给抽象方法,于是我们的LibraryApp就变成了

public class LibraryApp extends App {
    private static String welcomeMessage = "Welcome to Biblioteca library";

    public static void main(String[] args) throws IOException {
        (new LibraryApp()).run();
    }

    protected void init() {
        System.out.println(welcomeMessage);
    }

    protected void loop() {
        String key = "";
        Scanner sc = new Scanner(System.in);
        key = sc.nextLine();

        if(key.equals("Quit")){
            setQuit();
        }
    }

    protected void exit() {
        System.out.println("Quit Library");
    }
}

然而,如书中所说这是一个很好的用于示范TEMPLATE METHOD模式的例子,却不是一个合适的例子。

其他

参考书目

  • 《Head First 设计模式》
  • 《设计模式》
  • 《敏捷软件开发 原则、模式与实践》

关于我

Github: @phodal     微博:@phodal     知乎:@phodal    

微信公众号(Phodal)

围观我的Github Idea墙, 也许,你会遇到心仪的项目

QQ技术交流群: 321689806
comment

Feeds

RSS / Atom

最近文章

关于作者

Phodal Huang

Engineer, Consultant, Writer, Designer

ThoughtWorks 技术专家

工程师 / 咨询师 / 作家 / 设计学徒

开源深度爱好者

出版有《前端架构:从入门到微前端》、《自己动手设计物联网》、《全栈应用开发:精益实践》

联系我: h@phodal.com

微信公众号: 最新技术分享

标签