門面模式【Facade Pattern】也叫外觀模式,是1種比較經常使用的封裝模式,其定義以下:
【要求1個子系統的外部與其內部的通訊必須通過1個統1的對象進行。門面模式提供1個高層次的接口,使得子系統更容易使用】
門面模式重視“統1的對象”,也就是提供了1個訪問子系統的接口,除這個接口不允許有任何訪問子系統的行動產生。
門面模式的系統類圖以下:
類圖就是這么簡單,但是意義其實很復雜
Subsystem Classes 是所有子系統所有類的簡稱,它可能代表1個類,也可能代表幾10個對象的集合。不管多少對象,我們都將他們化為子系統的范疇,結構如圖:
【不管子系統有多麻煩,外部只能通過這個【Facade——門面對象】來進行通訊】
1般情況下,Facade會將所有從客戶端發來的要求委派到相應的子系統去,也就是說該角色沒有實際的 業務邏輯,是1個拜托類。
下面是門面模式的通用源碼
//子系統源代碼
public class ClassA{
public void doSomethingA(){
//業務邏輯
}
}
public class ClassB{
public void doSomethingB(){
//業務邏輯
}
}
public class ClassC{
public void doSomethingC(){
//業務邏輯
}
}
//門面對象
public class Facade{
//被拜托的對象
private ClassA a = new ClassA();
private ClassB b = new ClassB();
private ClassC c = new ClassC();
//提供給外部訪問的方法
public void methodA(){
this.a.doSomethingA();
}
public void methodB(){
this.b.doSomethingB();
}
public void methodC(){
this.c.doSomethingC();
}
}
下面用1個例子來看1下具體的門面模式
例子:【我要投遞信件】
我們都寫過紙質的信件,比如給女朋友寫情書甚么的。寫信的進程大家應當都記得——先寫信的內容,然后寫信封,在把信放到信封里,封好,投遞到信箱中進行投遞。雖然簡單,但是這4個步驟都是不可或缺的!
首先我們看如果不使用門面模式應當是怎樣實現的
public interface ILetterProcess {
//首先要寫信的內容
public void writeContext(String context);
//其次寫信封
public void fillEnvelope(String address);
//然后郵遞
public void letterInotoEnvolope();
//然后郵遞
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 letterInotoEnvolope() {
System.out.println("把信放到信封中...");
}
@Override
public void sendLetter() {
System.out.println("郵遞信件...");
}
}
public class Client {
public static void main(String[] args) {
ILetterProcess letterProcess = new LetterProcessImpl();
letterProcess.writeContext("Hello, It's me, do you know Who I am? I'm your old lover.");
letterProcess.fillEnvelope("Happy Road No. 666, God Province, Heaven");
letterProcess.letterInotoEnvolope();
letterProcess.sendLetter();
}
}
Output:
/**
填寫信的內容... Hello, It's me, do you know Who I am? I'm your old lover.
填寫收信人的姓名和地址...Happy Road No. 666, God Province, Heaven
把信放到信封中...
郵遞信件...
*/
上面的代碼與高內聚的要求相差甚遠,更不說迪米特原則和接口隔離原則了。
怎樣辦呢?
郵局出了新的業務,你告知我信的內容和地址,其余的我幫你弄定。
加了1個郵局的類
public class ModenPostOffice {
//這就是門面對象
private ILetterProcess letterProcess = new LetterProcessImpl();
public void sendLetter(String context, String address){
letterProcess.writeContext(context);
letterProcess.fillEnvelope(address);
letterProcess.letterInotoEnvolope();
letterProcess.sendLetter();
}
}
修改場景類
public class Client {
public static void main(String[] args) {
ModenPostOffice modenPostOffice = new ModenPostOffice();
String context = "Hello, It's me, do you know Who I am? I'm your old lover.";
String address = "Happy Road No. 666, God Province, Heaven";
modenPostOffice.sendLetter(context, address);
}
}
//Output
/**
填寫信的內容... Hello, It's me, do you know Who I am? I'm your old lover.
填寫收信人的姓名和地址...Happy Road No. 666, God Province, Heaven
把信放到信封中...
郵遞信件...
*/
下面我們要通過1個要求來看1下門面模式的優點:
要求:【新建發送之前請先檢查信件是不是安全】
//增加了檢查信件的Police類
public class Police {
public void checkletter(ILetterProcess letterProcess){
System.out.println(letterProcess + " 信件已被檢查過了...");
}
}
//修改ModenPostOffice
public class ModenPostOffice {
//這就是門面對象
private ILetterProcess letterProcess = new LetterProcessImpl();
private Police letterPolice = new Police();
public void sendLetter(String context, String address){
letterProcess.writeContext(context);
letterProcess.fillEnvelope(address);
letterPolice.checkletter(letterProcess);
letterProcess.letterInotoEnvolope();
letterProcess.sendLetter();
}
}
場景類完全1樣
//Output
/**
填寫信的內容... Hello, It's me, do you know Who I am? I'm your old lover.
填寫收信人的姓名和地址...Happy Road No. 666, God Province, Heaven
com.sdkd.LetterProcessImpl@74a14482 信件已被檢查過了...
把信放到信封中...
郵遞信件...
*/
可以看到這個新的要求對客戶是透明的,他甚么都不用管,只是負責告知郵局內容和地址就能夠了。
不改變子系統對外暴露的接口 、方法,只改變內部的處理邏輯,其他兄弟模塊的調用產生了想要得到結果,這確切是1個非常好的設計。這就是門面模式。
最后的UML圖以下,層次模塊很明顯
門面模式的優點:
1、減少系統的相互依賴
2、提供了靈活性
3、提供了安全性
門面模式的缺點:
門面模式不符合開閉原則,1旦出錯風險很大。
門面模式的使用處景:
1、為1個復雜的模塊或子系統提供1個供外界訪問的接口
2、子系統相對獨立,對外界來講訪問只要暗箱操作就能夠
3、預防低水平人員帶來的風險分散。
上一篇 Codeforces Round #385 (Div. 2) C. Hongcow Builds A Nation 并查集+貪心+組合學、圖論、dfs
下一篇 802.11ax前瞻1:協議簡介