在shell脚本里使用Abstract Factory的设计模式

Abstract Factory的定义见 wikipedia

在不同的平台下,我需要分别定义一组函数/命令, 比如 of ,其作用是在命 令行下用图形程序打开参数指定的文件或URL( of 是 “open file”之意);又 比如 oc ,“open container”,其作用是用文件管理器打开参数指定的文件所 在文件夹并选定该文件。

这个需求非常符合 Abstract Factory 设计模式的使用场景,请听我慢慢道来。

比如,重复上面的叙述,虚拟的 of 的定义为:在命令行下用图形程序打开参 数指定的文件或URL。具体的 of 的定义则是(以linux为例):在linux命令行 下用linux图形程序打开参数指定的文件或URL。 (比如 of readme.txt ,在 Windows平台下应该用notepad.exe打开该文本文件(取决于注册表中的文件关 联),而在Linux平台下应该用相应的例如gedit程序来打开此文件。)

of 命令最早是受到了 cygwin 下 cygstart 命令的启发。而 cygstart 其 实是受 windows 下 cmd.exe 自带的 start 命令启发;并且 Linux 底下也有类 似功能的 xdg-open 和 gnome-open 命令。但非要去记不同的环境下一定要敲不 同的命令实在是一件让人痛苦的事情,就像面象对象编程用虚函数解决掉了 giant “switch” 语句的问题,我们也可以用抽象工厂模式来抹除这种痛苦。)

我需要一个工厂虚类,通过它我可以创建虚拟的 of/oc 命令。在linux下,有 一个具体的工厂,通过它我可以创建具体的linux版本的 of/oc 命令;在 windows下,也有一个具体的工厂,通过它我可以创建具体的windows版本的 of/oc 命令。

如果一定要把类、对象的比喻进行到底的话,这里所说的工厂虚类我们可以把它 等同于文件的概念。则相应的linux工厂实类的定义就是“一个实现了linux版 of 命令创建功能的文件”。在面向对象编程中,虚类是无法创建直接对应于它的对象 的;但linux工厂实类我们可以为它创建一个对象,也就是一个实际存在于文件系 统中的文件(而不再是口头说说的、概念上的文件): $HOME/.bashrc-linux (注意我们只能创建一个这样的对象,如果你自己把这个对象拷贝一份到 $HOME/.bashrc-linux.bak 的话也是可以的——但系统不认,请问这叫什么 design pattern?)。接下来linux版 of 实类的定义类似于 function of() { ... } ,要为它创建一个对象的话,我们需要把这段定义交给bash命令行执行 一下,见下图:

create-of.png

.bashrc-linux 这个工厂里,我们这样定义linux版的 of

function of() {
    gnome-open "$@" > /dev/null 2>&1
}

而在 .bashrc-windows 这个工厂里,我们这样定义windows版的 of

function of() {
     cygstart "$@" > /dev/null 2>&1
}

抽象工厂模式里一般在程序刚开始的时候决定使用哪个具体的工厂,所以在我的 .bashrc 里:

if test `uname` = Linux; then
    factory=~/.bashrc-linux
else
    factory=~/.bashrc-windows
fi

最后,我们让工厂开工,一次性制造出我们想要的 of/oc 以及其他 概念上平 台无关,实现上平台相关,故曰之抽象一系列,故曰之工厂 的命令:

function Start() {
    source "$2"
}
Start the "$factory" and claim deep understanding about Abstract Factory design pattern\! No kidding\!

这就是我对抽象工厂模式的理解,您觉得呢?