Facade 外觀模式 外觀模式(Facade Pattern)是一種結構型設計模式,它為子系統提供一組統一的接口。這個接口使子系統更容易使用。 以現實的例子做舉例,很像我們打電話給客服,客服會幫我們處理我們的問題,而我們不需要知道客服是如何處理的,只需要知道我們的問題被解決了。
結構
Facade: 提供統一的接口,並且知道如何將請求傳遞給子系統的相應對象。
Additional Facade: 可以有多個外觀,這取決於系統的複雜性。
subsystem: 這是子系統的一組類,它實現了子系統的功能。子系統並不知道外觀的存在。
範例 假設我們要設計一個「飯店預訂系統」,其需求包含:
檢查房間是否可預訂
預訂房間
進行付款
記錄與維護顧客資料
內部子系統可能包含:
RoomService:與房間相關的業務(檢查房間可用性、預訂、取消等)
PaymentService:與付款相關的業務(信用卡或其他支付方式)
CustomerService:與顧客資料維護相關
重構前 RoomService
1 2 3 4 5 6 7 8 9 10 11 12 public class RoomService { public boolean isRoomAvailable (int roomNumber) { System.out.println("Checking availability for room: " + roomNumber); return true ; } public void bookRoom (int roomNumber) { System.out.println("Booking room: " + roomNumber); } }
PaymentService
1 2 3 4 5 6 7 public class PaymentService { public boolean pay (String customerName, double amount) { System.out.println("Paying " + amount + " for " + customerName); return true ; } }
CustomerService
1 2 3 4 5 6 public class CustomerService { public void addCustomer (String customerName, String contactInfo) { System.out.println("Adding customer: " + customerName); } }
客戶端程式(未使用外觀模式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class ClientWithoutFacade { public static void main (String[] args) { String customerName = "Alice" ; String contactInfo = "alice@example.com" ; int roomNumber = 101 ; double amount = 2000.0 ; CustomerService customerService = new CustomerService (); customerService.addCustomer(customerName, contactInfo); RoomService roomService = new RoomService (); boolean available = roomService.isRoomAvailable(roomNumber); if (available) { roomService.bookRoom(roomNumber); PaymentService paymentService = new PaymentService (); boolean paymentSuccess = paymentService.pay(customerName, amount); if (paymentSuccess) { System.out.println("Room booked and payment successful!" ); } } } }
缺點
客戶端必須了解並直接操作 CustomerService、RoomService、PaymentService 等多個類別。
程式碼分散在客戶端,當要新增或修改預訂流程時,勢必會影響各個呼叫邏輯。
耦合度高,客戶端需要了解不同子系統的順序、參數與各種細節。
重構後 HotelFacade
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class HotelFacade { private CustomerService customerService; private RoomService roomService; private PaymentService paymentService; public HotelFacade () { this .customerService = new CustomerService (); this .roomService = new RoomService (); this .paymentService = new PaymentService (); } public boolean bookHotel (String customerName, String contactInfo, int roomNumber, double amount) { customerService.addCustomer(customerName, contactInfo); if (roomService.isRoomAvailable(roomNumber)) { roomService.bookRoom(roomNumber); boolean paymentSuccess = paymentService.pay(customerName, amount); if (paymentSuccess) { System.out.println("Book hotel and payment successful!" ); return true ; } } System.out.println("Booking failed!" ); return false ; } }
客戶端程式(使用外觀模式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class ClientWithFacade { public static void main (String[] args) { String customerName = "Alice" ; String contactInfo = "alice@example.com" ; int roomNumber = 101 ; double amount = 2000.0 ; HotelFacade hotelFacade = new HotelFacade (); boolean result = hotelFacade.bookHotel(customerName, contactInfo, roomNumber, amount); if (result) { System.out.println("Enjoy your stay!" ); } else { System.out.println("Sorry, we could not book your room." ); } } }
優點
客戶端只需要了解並操作 HotelFacade
這個統一介面,不需要了解內部子系統的細節。
程式碼集中在 HotelFacade,當要新增或修改預訂流程時,只需要修改 HotelFacade 即可。
降低耦合度,客戶端不需要了解不同子系統的順序、參數與各種細節
。
提高了安全性,客戶端無法直接操作子系統。