門面模式( Facade Pattern) 也叫作外觀模式, 是一種比較經常使用的封裝模式, 其定義以下:設計模式
Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.( 要求一個子系統的外部與其內部的通訊必須經過一個統一的對象進行。 門面模式提供一個高層次的接口, 使得子系統更易於使用。 )安全
這個角色沒有沒有實際的業務, 而是一個委託類, 客戶端調用這個此角色的方法, 此角色會將客戶端的請求委派給相應的的子系統中, 客戶端不須要在乎子系統的實現細節.ide
一個門面能夠擁有一個或者多個子系統, 一個子系統不是單獨的一個類, 而是一個類的集合. 子系統並不知道門面的存在, 對於子系統來講, 門面只是另外一個客戶端而已.spa
咱們要用最浪漫最原始的方式去表白, 寫一份情書!設計
定義寫信過程的藉口:code
public interface ILetterProcess { // 寫信的內容 public void writeContext(String context); // 寫信封 public void fillEnvelope(String address); // 把信放到信封 public void letterIntoEnvelope(); // 郵遞 public void sendLetter(); }
實現寫信的過程對象
public class LetterProcessImpl implements ILetterProcess { @Override public void writeContext(String context) { System.out.println("填寫信的內容... " + context); } @Override public void fillEnvelope(String address) { System.out.println("填寫收件人地址及姓名... " + address); } @Override public void letterIntoEnvelope() { System.out.println("把信放到信箱中..."); } @Override public void sendLetter() { System.out.println("郵遞信件... "); } }
爲了告白, 咱們須要四個步驟, 對應寫信接口的四個方法, 並且這個四個方法是須要按照順序的, 不能顛倒:接口
public class Client { public static void main(String[] args) { ILetterProcess process = new LetterProcessImpl(); process.writeContext("你好, 我喜歡你!"); process.fillEnvelope("寧波市江北區風華路201號寧波工程學院, xb"); process.letterIntoEnvelope(); process.sendLetter(); } }
運行結果:rem
填寫信的內容... 你好, 我喜歡你! 填寫收件人地址及姓名... 寧波市江北區風華路201號寧波工程學院, xb 把信放到信箱中... 郵遞信件...
可是這樣會有一點問題, 首先咱們必需要知道它們的順序, 若是順序出現錯誤, 則達不到預期的目標, 這樣的寫法不符合迪米特法則和接口隔離原則. 並且, 若是要同時要和不少女孩子表白(霧, 這是什麼操做)的話, 每次都要這樣, 累的要死. 好在如今郵局推出一個代寫情書的服務, 只要提供信的內容和地址收信人就好了, 其餘的步驟郵局會完成的(霧, 告白能不能有點誠意), 很是好:it
public class Facade { private ILetterProcess process = new LetterProcessImpl(); public void sendLetter(String context, String address) { process.writeContext(context); process.fillEnvelope(address); process.letterIntoEnvelope(); process.sendLetter(); } }
有了這種人性化的服務, 咱們就能更方便的寫信了:
Facade facade = new Facade(); String context = "你好, 我喜歡你!"; String address = "寧波市江北區風華路201號寧波工程學院, xb"; facade.sendLetter(context, address);
結果是和上面一致的, 可是更加簡化了, 咱們只須要提供內容和地址就好了, 其餘什麼都不用去管, 並且易於擴展.
如今, 郵局須要覈查信件是否安全, 須要進行審查, 因此咱們須要對Facade進行擴展:
public class Police { public void checkLetter(ILetterProcess process) { System.out.println(process + " 信件已經審查..."); } }
public class Facade { private ILetterProcess process = new LetterProcessImpl(); private Police police = new Police(); public void sendLetter(String context, String address) { process.writeContext(context); process.fillEnvelope(address); process.letterIntoEnvelope(); police.checkLetter(process); process.sendLetter(); } }
而後再執行一次Client:
填寫信的內容... 你好, 我喜歡你! 填寫收件人地址及姓名... 寧波市江北區風華路201號寧波工程學院, xb 把信放到信箱中... io.ride.facade_pattern.LetterProcessImpl@61bbe9ba 信件已經審查... 郵遞信件...
Client程序並無作出任何修改, 可是能夠看到已經增長了審查信件的步驟.
門面模式裏全部的依賴都是對門面對象的依賴, 與子系統沒有關係
無論子系統內部如何變化, 只要不影響到門面對象,對客戶端來講就是沒有變化. 靈活性提升了.
想要訪問子系統的業務系統, 必須經過門面系統來訪問, 不然沒法訪問.
無論子系統內部如何變化, 只要不影響到門面對象,若是門面對象出現錯誤,那麼只有修改門面角色的代碼.