當子系統類別眾多、介面複雜時,提供一個**統一的高層介面** (Facade),讓客戶端能簡單完成常見任務,同時保留直接使用底層類別的彈性。
子系統:顯示器、主機板、CPU、記憶體、顯示卡… 各有複雜參數。
@interface Display : NSObject
- (void)chooseDisplay:(NSString *)type;
@end
@implementation Display
- (void)chooseDisplay:(NSString *)type { NSLog(@"選擇顯示器:%@", type); }
@end
@interface MainBoard : NSObject
- (void)chooseMainBoard:(NSString *)type;
@end
@implementation MainBoard
- (void)chooseMainBoard:(NSString *)type { NSLog(@"選擇主機板:%@", type); }
@end
@interface CPU : NSObject
- (void)chooseCPU:(NSString *)type;
@end
@implementation CPU
- (void)chooseCPU:(NSString *)type { NSLog(@"選擇 CPU:%@", type); }
@end
@interface ProClient : NSObject
- (void)assembleCustom;
@end
@implementation ProClient
- (void)assembleCustom {
Display *d = [Display new]; [d chooseDisplay:@"AOC 27\""];
MainBoard *mb = [MainBoard new]; [mb chooseMainBoard:@"ASUS ROG"];
CPU *cpu = [CPU new]; [cpu chooseCPU:@"i9-13900K"];
// ... 記憶體、顯卡、電源...
}
@end
@interface MacBookPro : NSObject
- (void)chooseConfiguration;
@end
@implementation MacBookPro
- (void)chooseConfiguration {
Display *d = [Display new]; [d chooseDisplay:@"Samsung 13\" Retina"];
MainBoard *mb = [MainBoard new]; [mb chooseMainBoard:@"Apple M2 Mainboard"];
CPU *cpu = [CPU new]; [cpu chooseCPU:@"Apple M2 Pro"];
// 內部封裝細節,客戶端無需知道
}
@end
@interface CasualClient : NSObject
- (void)buyComputer;
@end
@implementation CasualClient
- (void)buyComputer {
MacBookPro *mbp = [MacBookPro new];
[mbp chooseConfiguration]; // 只需呼叫一個方法
}
@end
Client (CasualClient)
│
▼
Facade (MacBookPro)
│
├──▶ Display
├──▶ MainBoard
├──▶ CPU
└──▶ ... (其他子系統)
| 優點 | 缺點 |
|---|---|
| 降低客戶端與子系統耦合 | 若外觀過於龐大,違反單一職責 |
| 簡化常見使用情境 | 可能隱藏子系統重要細節 |
| 保留進階用法彈性 (繼續可直接用子系統) | 增加一層間接呼叫 |
| 利於分層架構 (Facade 作為層邊界) |
AFNetworking 的 AFHTTPSessionManager 是 NSURLSession 的外觀NSPersistentContainer 封裝 NSPersistentStoreCoordinator 等AnalyticsManager 封裝 Firebase、AppsFlyer、Adjust 等FileManager、UserDefaults 皆是底層 C API 的外觀protocol DisplayChoosable { func chooseDisplay(_ type: String) }
protocol MainBoardChoosable { func chooseMainBoard(_ type: String) }
protocol CPUChoosable { func chooseCPU(_ type: String) }
struct MacBookProFacade {
let display: DisplayChoosable
let mainBoard: MainBoardChoosable
let cpu: CPUChoosable
func chooseConfiguration() {
display.chooseDisplay("Samsung 13\" Retina")
mainBoard.chooseMainBoard("Apple M2 Mainboard")
cpu.chooseCPU("Apple M2 Pro")
}
}