設計模式:外觀(Facade)模式
一、前言
外觀模式是一種非常簡單的模式,簡單到我們經常都會使用,比如對於類A和B,如果兩者需要交互,經過一定的處理過程才能實現某一個具體的功能,那么我們可以將這個處理的過程定義為一個新的類,然后在這個類里面將類A和B的處理步驟整合在一起,對於外界我們只暴露新的類中的這個接口,這樣代碼的復用性就非常的好了,可以將這些代碼作為組件去讓其他程序去使用,這在我們的開發之中是非常常見的。甚至我們可以將抽象工廠模式中創建產品的接口當做外觀模式的一種應用,這也是一種整合。對於模板方法,其實我們也是在父類之中面向抽象編程的,將一些關系整合起來,不過差別還是非常明顯的,在外觀模式中沒有繼承關系,是新建一個類來整合其它類之間復雜的相互依賴,調用等關系,因此外觀模式比較直觀。
二、代碼
DataBase 類:
1 package zyr.dp.facade; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.util.Properties; 7 8 public class DataBase { 9 private DataBase(){ 10 11 } 12 public static Properties getProperties(String dbName){ 13 Properties pro=new Properties(); 14 15 try { 16 pro.load(new FileInputStream(dbName+".txt")); 17 } catch (FileNotFoundException e) { 18 e.printStackTrace(); 19 } catch (IOException e) { 20 e.printStackTrace(); 21 } 22 return pro; 23 } 24 25 }
HTMLWriter類:
1 package zyr.dp.facade; 2 3 import java.io.IOException; 4 import java.io.Writer; 5 6 public class HTMLWriter { 7 8 private Writer writer; 9 public HTMLWriter(Writer writer){ 10 this.writer=writer; 11 } 12 public void title(String theTitle){ 13 try { 14 writer.write("<html><head><title>"+theTitle+"</title></head><body>\n"); 15 writer.write("<h1>"+theTitle+"</h1>\n"); 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } 19 } 20 public void paragraph(String msg){ 21 try { 22 writer.write("<p>"+msg+"</p>\n"); 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } 26 } 27 public void link(String href,String caption){ 28 paragraph("<a href=\""+href+"\" >"+caption+"</a>"); 29 } 30 public void mailTo(String mailAddr,String username) { 31 link("mailto:"+mailAddr,username); 32 } 33 public void close() { 34 try { 35 writer.write("</body></html>\n"); 36 writer.close(); 37 } catch (IOException e) { 38 e.printStackTrace(); 39 } 40 } 41 }
PageMaker類:
1 package zyr.dp.facade; 2 3 import java.io.FileWriter; 4 import java.io.IOException; 5 import java.util.Properties; 6 7 public class PageMaker { 8 private PageMaker(){ 9 } 10 public static void makePage(String mailAddr,String filename) throws IOException{ 11 Properties pro=DataBase.getProperties("mailData"); 12 String username=pro.getProperty(mailAddr); 13 HTMLWriter html=new HTMLWriter(new FileWriter(filename)); 14 html.title("編程之美"); 15 html.paragraph("歡迎 "+username+" 來到我的程序空間!"); 16 html.paragraph("這里有你想要的一切~~"); 17 html.mailTo(mailAddr, username); 18 html.close(); 19 System.out.println("為"+username+"創建"+filename+"文件成功!"); 20 } 21 22 }
main類:
1 package zyr.dp.facade; 2 3 import java.io.IOException; 4 5 public class Main { 6 7 public static void main(String[] args) { 8 try { 9 PageMaker.makePage("2655100328@qq.com", "my_html.html"); 10 } catch (IOException e) { 11 e.printStackTrace(); 12 } 13 } 14 15 }
mailData存放的位置和內容:(注意如果使用相對地址,對於java程序來說src的上一級就是相對地址的起始地址,如果要放到src里面可以使用“./src/...”)。
運行結果:
雖然程序很簡單,但是要注意的地方一點也不少,首先就是我們要將外觀模式的接口對應的類(pageMaker)以及一些不用生成對象的工具類的構造函數設為私有,不讓外部類去創建實例,其次,我們要注意properties讀取文件的時候使用相對路徑應該從哪個地方開始讀寫,另外當我們的程序變得復雜的時候,如果將這些類封裝成一個模塊,如何防止類外的對象訪問我們的類呢,可以將除了facade類之外的類的屬性設為默認的,這樣就能很好的實現高內聚低耦合的設計思想了。這些類本來沒關系,但是通過一個整合之后,產生了一定的關聯,在實際開發中可能形成遞歸結構,那就是一個facade模式中使用了很多其他的facade模式,這樣不斷地實現下去,形成一個facade模式樹,因此靈活使用設計模式至關重要。
三、總結
facade外觀模式是一種非常常用的模式,特別是在組織一些復雜的相互調用的邏輯的時候,為外界提供統一的接口(API),可以看到在設計模式中,最常用的應該就是模板方法和facade模式了,很多時候很多需求需要我們認真的取舍,人無遠慮必有近憂,同樣的,只有為以后的可復用性、可擴展性來考慮,我們的代碼才是好的代碼。