概述
今天要說的外觀模式是一個相對簡單的設計模式,而且在日常的開發中,可能你也會時常使用它,只是你可能並未想過這是一個設計模式。本文會從一些實例著手,來對本文要說明的外觀模式進行盡可能全面的講解。希望你有益。
引言
這裡插入一條引言的目的是讓你回想一下,在你日常開發中何時用到了外觀模式。
可能你的 boss 會這樣安排你一個任務。這可能是個核心模組,模組會有它的一個功能,只是你的 boss 可能只想要你提供一個給他呼叫的介面。他會這麼跟你說:嗨,小明,我們現在的這個系統裡需要一個核心的功能 P0,它就交給你實現吧。你只要給我可以呼叫的介面就好了,你程式碼的內部邏輯我不需要知道的。去做吧。
如果你時常被安排這樣的任務,我想你應該已經掌握外觀模式了。
定義
外觀模式提供了一個統一的接口,用來存取子系統中的一群接口。外觀模式定義一個高層接口,讓子系統更容易使用。
非外觀模式
這裡我就使用《大話設計模式》書中的例子了,感覺這個例子還是挺形象的。現在假設你是個股民(只是博主不炒股,也不知道這裡會不會有說得不對的地方,如果有你就當沒看見吧。。^_^),你想做一些理財活動。你看中了兩支股票、一支國債和一支房地產。
如果讓你現在來寫這份程式碼,你的程式碼框架可能會像下面的這幅類別圖:
這裡只列舉了股票的程式碼,是因為其他理財活動的邏輯與股票的邏輯是一致的。冗餘的程式碼除了佔地方之外並沒有再多的好處了。
StockA.java
public class StockA { private int stockCount = 0; public void sell(int count){ stockCount -= count; System.out.println("卖了" + count + "支 A 股票"); } public void buy(int count){ stockCount += count; System.out.println("买了" + count + "支 A 股票"); } public int getStockCount() { return stockCount; } }
下面的程式碼是處理理財者的,對於一個簡單地買進買下邏輯,理財者都要花費這麼多的程式碼處理,實在是折磨人嘛。
Investors.java
public class Investors { public static void main(String[] args) { StockA stockA = new StockA(); StockB stockB = new StockB(); NationalDebt debt = new NationalDebt(); RealEstate estate = new RealEstate(); stockA.buy(100); stockB.buy(200); debt.buy(150); estate.buy(120); stockA.sell(100); stockB.sell(200); debt.sell(150); estate.sell(120); } }
上面說的這些是在沒有使用外觀模式的情況下寫的程式碼。也就是說下面要說的外觀模式可以讓程式碼更簡單明了。
外觀模式
在上面的非外觀模式中,我們看到了一些不是很友善的程式碼邏輯。而外觀模式可以基於更高層次的封裝,從而達到對呼叫者更加透明。以下是修改後的外觀模式類別圖:
FundFacade.java
public class FundFacade { private StockA stockA = null; private StockB stockB = null; private NationalDebt debt = null; private RealEstate estate = null; public FundFacade() { stockA = new StockA(); stockB = new StockB(); debt = new NationalDebt(); estate = new RealEstate(); } public void buyAll(int count) { stockA.buy(count); stockB.buy(count); debt.buy(count); estate.buy(count); } public void sellAll(int count) { stockA.sell(count); stockB.sell(count); debt.sell(count); estate.sell(count); } public void buyStockA(int count) { stockA.buy(count); } public void sellNationalDebt(int count) { debt.sell(count); } }
上面的程式碼則是外觀的核心類別:FundFacade。在理財系統中的所有操作都可以透過這個類別來實現。你透過這個類可以很方便地實現對股票、國債、房地產等理財項目的操作,而不用關心裡面究竟是怎麼處理的。這是對使用者來說是件好事,不是嗎?
來看看用戶的操作吧(當然上面圖類已經反映了絕大部分效果了),這是用戶的程式碼邏輯:
Investors.java
public class Investors { public static void main(String[] args) { FundFacade facade = new FundFacade(); facade.buyAll(120); facade.buyStockA(50); facade.sellAll(80); } }
看看,用戶只要告訴FundFacade 類,買入什麼、賣出什麼、買多少、賣多少,就可以達到目的。實在是太方便了。
看看股票 A 的代碼吧,其實它並什麼實質的變化。這也是外觀模式的魅力所在,它不用你去修改原來子系統的程式碼,只要做一件事,建立更高層次的封裝。當然,這裡我做了一些簡單地修改,StockA 的存取權限。既然要對使用者透明,那麼我的子系統就沒有必要再對使用者開放了,不是嗎?因為我們已經有專業的外交官- FundFacade。
StockA.java
class StockA { private int stockCount = 0; void sell(int count){ stockCount -= count; System.out.println("卖了" + count + "支 A 股票"); } void buy(int count){ stockCount += count; System.out.println("买了" + count + "支 A 股票"); } int getStockCount() { return stockCount; } }
外觀模式是一個相對簡單的設計模式,你可以輕鬆掌握並使用它。只是我想說,外觀模式也會有一定的限制。相信你已經發現了。
由於我們把子系統所有的操作都交給了 FundFacade 類別來處理,所以我們就受到了 FundFacade 類別的約束了。例如上面的 FundFacade 類別中並沒有實現單獨對 StockB 的操作,那麼我們就不能單獨對 StockB 進行操作了,除非你在 FundFacade 類別中封裝一個對 StockB 操作的介面。
外觀模式的應用
上面的描述中我們不僅知道瞭如何使用外觀模式,也了解了外觀模式的局限,所以我們應該站在客觀的立場,有選擇性地使用它。這裡說一個我在工作中使用外觀模式的例子吧。
目前專案的老大讓我去實現一個系統中的某一個模組,我想這應該是一個核心模組吧。這個模組的功能是,檢查一個資料夾下的所有檔案是否包含了敏感資訊。而這個模組中會有很多小的子模組(當然老大並不會關心這些子模組做的事情),例如AC 自動機的模式匹配、壓縮檔案的全自動解壓縮、各種格式檔案(doc/xls/ ppt/zip/eml/rtf/pdf 等等,絕大部分的文件格式基本上都在吧)、日誌系統等等。
我不可能去跟老闆說,你要完成的功能是要先去幹嘛、再去幹嘛、再去幹嘛、再去幹嘛… …
哦,天啦。煩死了,你能對它封裝一下嗎? (當然,這些只是我的心理活動。事實上,我還沒有讓老大說明我的設計過程)
封裝過後,我只要告訴老大,去調用這個類別的這個方法就 ok 了。這樣老大那邊就不用操心裡面的邏輯了,雖然如果出了錯就是你的責任,可那也本該就 是你的責任啊。哈哈。 。 。
好了,扯蛋就到這裡。不管是上面正兒八經地模式詳解,還是下面的胡說八道,我都希望它可以讓你充分了解本文這個設計模式,學習並合理使用它。
以上就是Java設計模式-外觀模式的內容,更多相關內容請關注PHP中文網(www.php.cn)!