Java咖啡館——一個(gè)壓縮歸檔實(shí)用軟件(3)
發(fā)表時(shí)間:2023-12-26 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
黃糖故事
設(shè)計(jì)模式(Design Patterns)
建筑工程師Cristopher Alexander總結(jié)了建筑中的經(jīng)驗(yàn)教訓(xùn),發(fā)現(xiàn)有些問題總是一遍又一遍重復(fù)出現(xiàn),當(dāng)你總結(jié)出一套解決這種問題的核心方法以后,你只要放心使用這種解決方法即可,而完全不必再動(dòng)腦筋想其他的方案。雖然這句話很樸素,但是卻成了軟件工程中一種舉足輕重的方法學(xué)?設(shè)計(jì)模式的指導(dǎo)思想。
我們知道,建筑學(xué)有牛頓力學(xué)作為辯證的理論根據(jù),只要尊重科學(xué),就不可能設(shè)計(jì)出坍塌的建筑(即使坍塌,也是材料施工不過關(guān)或其他因素造成的)。但是,編寫軟件卻沒有這樣的理論根據(jù),因?yàn)槌绦蛑皇歉嬖V計(jì)算機(jī)語法,計(jì)算機(jī)只要如此這般依計(jì)而行,愚忠而已,而沒有機(jī)制能保證程序的語意符合人類的思想。因此,程序才會(huì)有BUG,即使比爾對(duì)Windows XP大吼:“我以老祖宗的名義不準(zhǔn)你有BUG!”,Windows XP能夠領(lǐng)會(huì)精神嗎?
雖然沒有徹底的解決方法,Erich Gamma等四位大師級(jí)的計(jì)算機(jī)科學(xué)家通過借鑒建筑學(xué)中的模式的概念,創(chuàng)造出軟件中的設(shè)計(jì)模式,通過精心萃取的23個(gè)模式,有效解決了軟件的設(shè)計(jì)問題,給程序加上了一定程度的模型語意。具體的,請(qǐng)閱讀這“四人幫”(Gang of Four)編寫的《Design Patterns》一書。值得一提的是,我們上一回編寫的名字解析器就是運(yùn)用了其中的Factory模式,結(jié)構(gòu)非常漂亮。
順便說一句,現(xiàn)在支持設(shè)計(jì)模式的工具也越來越多 ,如果你想有朝一日從Java程序員升級(jí)為呼風(fēng)喚雨的Java構(gòu)架師,這可是一門必修課哦!
4.正則表達(dá)式(Regular Expression)
說起正則表達(dá)式,即使不熟悉,你也會(huì)覺得非常眼熟。沒錯(cuò),現(xiàn)在的文本編輯軟件,無論是UltraEdit還是EditPlus,無一不支持正則表達(dá)式。可以說,不支持正則表達(dá)式的編輯器肯定是三流貨色啦。
理論上,正則表達(dá)式等價(jià)于有限自動(dòng)機(jī),能夠表達(dá)相當(dāng)豐富的語言,DOS中通配符的能力是無法望其項(xiàng)背的。學(xué)過編譯原理或者計(jì)算機(jī)理論的朋友一定很熟悉了,可是,如果從頭開講,恐怕這期所有版面都不夠。因此這里推薦你參考Sun免費(fèi)的Java Tutorial中的Regular Expressions一章,寫得很詳細(xì)。即使你熟悉計(jì)算機(jī)理論的正則表達(dá)式,也建議抽空看一看,因?yàn)镴ava采取的是類Perl風(fēng)格的語法,和理論書上有些出入。
比如我們要過濾出所有Java源程序。眾所周知,Java文件名必須以字母、美元符號(hào)或者下劃線開頭,然后可以由數(shù)字、字母、美元符號(hào)或者下劃線的任意組合,最后擴(kuò)展名是java。用正則表達(dá)式寫出來,就是“[a-zA-Z_$][a-zA-Z_$0-9]*\.java”(不含引號(hào))。
其中,[a-zA-Z_$]表示小寫字母a至z、大寫字母A至Z、美元符號(hào)或者下劃線任取其一;[a-zA-Z_$0-9]*表示小寫字母a至z、大寫字母A至Z、美元符號(hào)、下劃線以及0至9這十個(gè)數(shù)字的任意組合;“\.java”表示Java源程序的擴(kuò)展名,由于“.”在Java正則表達(dá)式中有特殊意義,所以“\.”才表示一個(gè)“.”符號(hào)。
當(dāng)然,Java正則表達(dá)式API中還有許多擴(kuò)充,可以簡寫為:[a-zA-Z_$][\w$]*\.java。
有了這些知識(shí),我們不難寫出支持正則表達(dá)式的文件過濾器FileFilter,源代碼如下:
public class FileFilter implements FilenameFilter {
private Pattern pattern;
public FileFilter(String regex) {
pattern = Pattern.compile(regex);
}
public boolean accept(File dir, String name) {
File file = new File(dir + "\\" + name);
return pattern.matcher(file.getName()).matches() && file.isFile();
}
}
Java中通過Pattern類來使用正則表達(dá)式。在FileFilter的構(gòu)造函數(shù)中,通過把regex參數(shù)傳遞給Pattern的compile()方法,便可以得到一個(gè)代表這個(gè)正則表達(dá)式的實(shí)例,之后便可以在accept()方法中調(diào)用了。具體地,當(dāng)且僅當(dāng)文件名滿足正則表達(dá)式并且這的確是一個(gè)文件時(shí),accept()方法返回True。
5.遞歸搜索子目錄
有了這兩個(gè)過濾器,遞歸搜索指定目錄中符合正則表達(dá)式的文件名就很容易了。先在項(xiàng)目中生成一個(gè)包含main方法的ExpZip類,然后添加一個(gè)recursiveAppend(File path, ArrayList list, String regex)方法,其中,參數(shù)path是指要搜索的文件夾,list是用來返回符合正則表達(dá)式的文件名的列表,regex自然是正則表達(dá)式了。源代碼如下:
private static void recursiveAppend(File path, ArrayList list, String regex) {
// 搜索path文件夾中符合要求的文件并添加到list里。
File[] files = path.listFiles(new FileFilter(regex));
if (files.length > 0) {
for (int i = 0; i < files.length; i++) {
list.add(files[i].getAbsolutePath());
}
}
// 遞歸搜索path子文件夾。
File[] subFolders = path.listFiles(new FolderFilter());
if (subFolders.length > 0) {
for (int i = 0; i < subFolders.length; i++) {
recursiveAppend(subFolders[i], list, regex);
}
}
}