終于考試完了,瞬間感覺輕松了許多,又可以安心地寫代碼了,下面進入今天的正題–外觀模式。
外觀模式,也稱門面模式,顧名思義,就是一個對象封裝了一系列相關的操作(行為),使得這些操作僅對外提供(暴露)方法(接口),客戶端根據這些外觀(暴露的接口)就可以簡單地完成一系列操作,達到了客戶端無需知道內部實現細節,只需知道對象的外觀就可以實現一系列行為,簡單來說就是面向對象的封裝。這一系列行為也就是一個系統的功能。
定義:通過一個統一的對象實現一個系統的外部與內部的通訊,提供了一個高層次的接口,使得系統功能更加透明,更加容易使用。
使用場景:
1.
為一個復雜系統提供一個簡單的接口。為一個復雜系統提供一個簡單的接口,對外部隱藏系統的內部實現,隔離變化,使得當這個系統因為不斷演化而不斷的修改,定制也可以更加容易地擴展使用,即對外部的使用是一樣的,客戶端無需知道內部發生了什么變化,隱藏了系統的內部實現,這也就是封裝的好處了。
1.
簡化子系統之間的依賴,降低它們之前的耦合。當不同的子系統需要使用其他系統的功能的時候,那么我們就需要構建一個層次結構的系統,這時我們通過外觀模式為這些子系統提供一個通訊接口,即每層的入口點。
優點:
1.
因為對客戶端隱藏了系統的細節,減少了客戶端對于系統的耦合,能夠擁抱變化。
1.
對系統一系列功能進行了整合,封裝,使得系統更加容易使用。
缺點:
1.
外觀類接口膨脹。因為我們外觀類需要封裝一系列相關的功能,這一系列相關的功能可能需要不同的類實現,那么我們不是簡單地給這個外觀類提供實現不同功能類,而是為每個實現不同功能的類提供一個接口,然后再使用的時候給這些接口提供實現類,這樣可以便于擴展,反之,外觀類接口必然膨脹,也增加了程序員的一定的負擔。
1.
違背了開閉原則,當業務出現變更的時候,可能需要直接修改外觀類(通常是修改外觀類中的接口的實現類)。
下面以現代智能機模擬實現外觀模式
代碼實現:
虛擬手機(接口)—-接打電話功能接口
~~~
public interface Phone {
/**
* 打電話
*/
public void call();
/**
* 掛斷
*/
public void handup();
}
~~~
虛擬相機(接口)—-拍照功能接口
~~~
/**
* 照相機
* @author lt
*
*/
public interface Camera {
public void open();
public void takePicture();
public void close();
}
~~~
真實的手機(實現類)
~~~
/**
* 以前的舊手機,非智能,只能打電話和掛電話
* @author lt
*
*/
public class PhoneImpl implements Phone{
@Override
public void call() {
System.out.println("打電話");
}
@Override
public void handup() {
System.out.println("掛斷電話");
}
}
~~~
真實的相機(實現類)
~~~
/**
* 三星相機
* @author lt
*
*/
public class SamsungCamera implements Camera{
@Override
public void open() {
System.out.println("打開相機");
}
@Override
public void takePicture() {
System.out.println("拍到了一個美女");
}
@Override
public void close() {
System.out.println("相機關閉了");
}
}
~~~
現代智能機(Android/Iphone)—-外觀類
~~~
/**
* 現代智能機 --- 集照相,視頻聊天,打電話于一身
* @author lt
*
*/
public class SmartPhone {
// 對應實現完成手機功能接口的實現類
public Phone phone = new PhoneImpl();
// 對應實現相機功能接口的實現類
public Camera camera = new SamsungCamera();
public void call() {
phone.call();
}
public void hangup() {
phone.handup();
}
public void takePicture() {
openCamera();
camera.takePicture();
closeCamera();
}
public void openCamera() {
camera.open();
}
public void closeCamera() {
camera.close();
}
/**
* 視頻通話
*/
public void videoChat() {
openCamera();
System.out.println("和妹子視頻聊天");
closeCamera();
}
}
~~~
SmartPhone是外觀類,這里具體是現代智能機,具有接打電話,拍照等功能,是這個模式核心類;Phone和Camera是兩個特定功能的接口,分別是接打電話的功能,拍照功能,相應的實現類是PhoneIml和SamsungCamera。這里給外觀類整了兩個接口,即Phone和Camera,這樣做的目的是以后要修改接打電話和拍照功能的實現時(如新的硬件)只需要將外觀類SmartPhone中的相應功能的接口實現類改變一下就可以了,其他的都不用改,這也就是面向接口編程的好處,和J2EE中的Service,Dao層都提供一個接口和相應實現類一樣,目的是一樣的,即便于修改擴展。
測試:
~~~
public class Test {
public static void main(String[] args) {
SmartPhone iphone7s = new SmartPhone();
// 用7s拍照
iphone7s.takePicture();
// 用7s視頻聊天
iphone7s.videoChat();
}
}
~~~
運行結果:

可以看到,現代的智能機既有一般手機的功能,也有相機的功能,使得我們只需要一部智能機就不需要專門為打電話買一個手機,專門為拍照買一個相機了,一部手機統統搞定,而且避免了許多麻煩,如我們點擊屏幕的相機(系統內置App)系統自動打開了相機,拍照完了以后系統自動將相機關閉,視頻聊天也一樣,這使得我們使用更加簡單,更加方便。
總結:
外觀模式使用也非常多,面向對象中的封裝也通常是使用了外觀模式,封裝不一定使用了外觀模式,但外觀模式一定需要封裝。通過外觀模式,使得復雜系統功能更加豐富,使用更加簡單。通過一個外觀類就可以操作整個系統,減少了用戶的使用成本,同時因為內部面向接口編程,使得使擴展維護更加簡單,從而使得系統可以容易地面對多變的場景,提升了系統的擴展性靈活性。