一、外觀模式的實現方式
外觀模式的核心是通過封裝復雜子系統的調用邏輯,為客戶端提供一個統一的簡單接口。以下是實現步驟及示例:
- 定義子系統類
子系統類負責實現具體功能,與外觀類解耦。例如,家庭影院系統中的投影儀、音響等組件:
// 子系統接口
interface TheaterControl {void on();void off();void setVolume(int volume);
}
// 具體子系統實現
class Projector implements TheaterControl {public void on() { System.out.println("投影儀開啟"); }public void off() { System.out.println("投影儀關閉"); }
}
class StereoSystem implements TheaterControl {public void on() { System.out.println("音響開啟"); }public void off() { System.out.println("音響關閉"); }public void setVolume(int volume) { System.out.println("音量設為:" + volume); }
}
- 創建外觀類
外觀類聚合子系統對象,提供高層接口,協調子系統操作:
public class HomeTheaterFacade {private TheaterControl projector;private TheaterControl stereo;public HomeTheaterFacade() {this.projector = new Projector();this.stereo = new StereoSystem();}// 統一接口:觀影模式public void watchMovie(String movie) {System.out.println("準備觀看:" + movie);projector.on();stereo.on();stereo.setVolume(50);}
}
- 客戶端調用
客戶端通過外觀類簡化復雜操作:
public class Client {public static void main(String[] args) {HomeTheaterFacade facade = new HomeTheaterFacade();facade.watchMovie("Java設計模式實戰");}
}
二、測試方法與Mockito框架應用
測試外觀模式時,需驗證其是否正確調用子系統方法。通過Mockito框架模擬子系統對象,確保外觀類邏輯正確。
- 基礎測試:驗證子系統方法調用
import static org.mockito.Mockito.*;
import org.junit.Test;
public class HomeTheaterFacadeTest {@Testpublic void testWatchMovie() {// 創建Mock對象TheaterControl mockProjector = mock(Projector.class);TheaterControl mockStereo = mock(StereoSystem.class);// 創建外觀類并注入Mock對象HomeTheaterFacade facade = new HomeTheaterFacade() {@Overridepublic TheaterControl getProjector() { return mockProjector; }@Overridepublic TheaterControl getStereo() { return mockStereo; }};// 執行外觀方法facade.watchMovie("測試電影");// 驗證子系統方法調用verify(mockProjector).on();verify(mockStereo).on();verify(mockStereo).setVolume(50);}
}
- 高級測試:異常處理與狀態驗證
模擬子系統異常,測試外觀類的容錯邏輯:
@Test
public void testWatchMovieWithException() {TheaterControl mockProjector = mock(Projector.class);when(mockProjector.on()).thenThrow(new RuntimeException("投影儀故障"));HomeTheaterFacade facade = new HomeTheaterFacade() {@Overridepublic TheaterControl getProjector() { return mockProjector; }};try {facade.watchMovie("測試電影");fail("預期拋出異常");} catch (RuntimeException e) {assertEquals("投影儀故障", e.getMessage());}
}
三、實現與測試的注意事項
- 實現最佳實踐
- 單一職責:外觀類僅負責協調子系統,避免包含業務邏輯。
- 接口隔離:子系統應通過接口與外觀類交互,增強擴展性。
- 線程安全:若外觀類被多線程訪問,需同步關鍵方法。
- 測試關鍵點
- 覆蓋所有子系統調用:確保每個子系統方法在測試中被驗證。
- 模擬異常場景:測試子系統故障時外觀類的容錯機制。
- 避免過度模擬:僅Mock必要子系統,保留真實依賴以測試完整流程。
四、總結
外觀模式通過封裝復雜子系統的調用邏輯,顯著降低客戶端耦合度。實現時需遵循接口隔離與單一職責原則,測試時利用Mockito框架驗證子系統交互。其核心價值在于簡化接口設計,但需注意對開閉原則的潛在違背及測試復雜度問題。