第8章 外观模式
8.1 配置相关范例
核心问题
游戏配置项复杂,直接调用业务类导致耦合度高:
图形配置类
class Graphic {
private : Graphic ( ) = default ; Graphic ( const Graphic& ) = delete ; Graphic& operator = ( const Graphic& ) = delete ; ~ Graphic ( ) = default ; public : static Graphic& getInstance ( ) { static Graphic instance; return instance; } void display ( bool enable) { std:: cout << "图形->是否全屏显示: " << ( enable ? "是" : "否" ) << std:: endl; } void effect ( bool enable) { std:: cout << "图形->是否开启特效: " << ( enable ? "是" : "否" ) << std:: endl; } void resolution ( int index) { std:: cout << "图形->分辨率设置: " << ( index== 0 ? "1920x1080" : index== 1 ? "1280x720" : "1024x600" ) << std:: endl; } void antialiasing ( bool enable) { std:: cout << "图形->是否开启抗锯齿: " << ( enable ? "是" : "否" ) << std:: endl; }
} ;
声音配置类(单件模式)
class Sound {
private : Sound ( ) = default ; Sound ( const Sound& ) = delete ; Sound& operator = ( const Sound& ) = delete ; ~ Sound ( ) = default ; public : static Sound& getInstance ( ) { static Sound instance; return instance; } void bgsound ( bool enable) { std:: cout << "声音->背景声音: " << ( enable ? "开启" : "关闭" ) << std:: endl; } void envirsound ( bool enable) { std:: cout << "声音->环境音效: " << ( enable ? "开启" : "关闭" ) << std:: endl; } void expsound ( bool enable) { std:: cout << "声音->表情声音: " << ( enable ? "开启" : "关闭" ) << std:: endl; } void setvolume ( int level) { std:: cout << "声音->音量设置: " << level << "%" << std:: endl; }
} ;
语音聊天类(单件模式)
class ChatVoice {
private : ChatVoice ( ) = default ; ChatVoice ( const ChatVoice& ) = delete ; ChatVoice& operator = ( const ChatVoice& ) = delete ; ~ ChatVoice ( ) = default ; public : static ChatVoice& getInstance ( ) { static ChatVoice instance; return instance; } void micvolume ( int level) { std:: cout << "语音->麦克风音量: " << level << "%" << std:: endl; } void micsens ( int level) { std:: cout << "语音->麦克风灵敏度: " << level << "%" << std:: endl; } void chatvolume ( int level) { std:: cout << "语音->聊天音量: " << level << "%" << std:: endl; }
} ;
客户端直接调用示例
int main ( ) { Graphic& graphic = Graphic :: getInstance ( ) ; graphic. display ( false ) ; graphic. effect ( true ) ; graphic. resolution ( 1 ) ; graphic. antialiasing ( true ) ; std:: cout << "------------------------" << std:: endl; Sound& sound = Sound :: getInstance ( ) ; sound. bgsound ( true ) ; sound. envirsound ( true ) ; sound. expsound ( false ) ; sound. setvolume ( 75 ) ; std:: cout << "------------------------" << std:: endl; ChatVoice& chat = ChatVoice :: getInstance ( ) ; chat. micvolume ( 80 ) ; chat. micsens ( 60 ) ; chat. chatvolume ( 90 ) ; return 0 ;
}
8.2 外观模式实现
模式结构(Mermaid类图)
Client
-main()
Facade
+LowConfComputer()
+HighConfComputer()
Graphic
+display()
+effect()
Sound
+bgsound()
+setvolume()
ChatVoice
+micvolume()
+chatvolume()
外观类实现
class ConfigFacade {
private : ConfigFacade ( ) = default ; ConfigFacade ( const ConfigFacade& ) = delete ; ConfigFacade& operator = ( const ConfigFacade& ) = delete ; ~ ConfigFacade ( ) = default ; public : static ConfigFacade& getInstance ( ) { static ConfigFacade instance; return instance; } void lowConfigSetup ( ) { Graphic& g = Graphic :: getInstance ( ) ; g. display ( true ) ; g. effect ( false ) ; g. resolution ( 2 ) ; g. antialiasing ( false ) ; Sound& s = Sound :: getInstance ( ) ; s. bgsound ( false ) ; s. envirsound ( false ) ; s. expsound ( false ) ; s. setvolume ( 15 ) ; ChatVoice& c = ChatVoice :: getInstance ( ) ; c. micvolume ( 20 ) ; c. micsens ( 50 ) ; c. chatvolume ( 60 ) ; } void highConfigSetup ( ) { Graphic& g = Graphic :: getInstance ( ) ; g. display ( false ) ; g. effect ( true ) ; g. resolution ( 0 ) ; g. antialiasing ( true ) ; Sound& s = Sound :: getInstance ( ) ; s. bgsound ( true ) ; s. envirsound ( true ) ; s. expsound ( true ) ; s. setvolume ( 50 ) ; ChatVoice& c = ChatVoice :: getInstance ( ) ; c. micvolume ( 100 ) ; c. micsens ( 100 ) ; c. chatvolume ( 100 ) ; }
} ;
客户端通过外观调用
int main ( ) { ConfigFacade& facade = ConfigFacade :: getInstance ( ) ; std:: cout << "【低配置电脑配置】" << std:: endl; facade. lowConfigSetup ( ) ; std:: cout << "\n【高配置电脑配置】" << std:: endl; facade. highConfigSetup ( ) ; return 0 ;
}
«main»
Client
-main()
ConfigFacade
+lowConfigSetup()
+highConfigSetup()
Graphic
+display()
+effect()
+resolution()
+antialiasing()
Sound
+bgsound()
+envirsound()
+expsound()
+setvolume()
ChatVoice
+micvolume()
+micsens()
+chatvolume()
8.3 家庭影院案例
系统架构(Mermaid组件图)
控制
控制
控制
控制
控制
客户端
HomeTheaterFacade
Screen
Light
Speaker
DVDPlayer
GameConsole
子系统实现
class Screen {
public : void on ( ) { std:: cout << "屏幕升起" << std:: endl; } void off ( ) { std:: cout << "屏幕降下" << std:: endl; } void setInput ( int input) { std:: cout << "设置输入源: " << ( input== 1 ? "HDMI" : "AV" ) << std:: endl; }
} ;
class Light {
public : void on ( ) { std:: cout << "灯光开启" << std:: endl; } void off ( ) { std:: cout << "灯光关闭" << std:: endl; } void dim ( int level) { std:: cout << "灯光调暗至: " << level << "%" << std:: endl; }
} ;
class Speaker {
public : void on ( ) { std:: cout << "音箱开启" << std:: endl; } void off ( ) { std:: cout << "音箱关闭" << std:: endl; } void setMode ( int mode) { std:: cout << "设置音效模式: " << ( mode== 1 ? "立体声" : "环绕声" ) << std:: endl; }
} ;
class DVDPlayer {
public : void on ( ) { std:: cout << "DVD播放器开启" << std:: endl; } void off ( ) { std:: cout << "DVD播放器关闭" << std:: endl; } void play ( const std:: string& movie) { std:: cout << "播放电影: " << movie << std:: endl; }
} ;
class GameConsole {
public : void on ( ) { std:: cout << "游戏机开启" << std:: endl; } void off ( ) { std:: cout << "游戏机关闭" << std:: endl; } void loadGame ( const std:: string& game) { std:: cout << "加载游戏: " << game << std:: endl; }
} ;
外观类协调
class HomeTheaterFacade {
private : Screen screen; Light light; Speaker speaker; DVDPlayer dvd; GameConsole game; public : void watchMovie ( const std:: string& movie) { std:: cout << "\n=== 开始观影 ===" << std:: endl; screen. on ( ) ; screen. setInput ( 1 ) ; light. dim ( 20 ) ; speaker. on ( ) ; speaker. setMode ( 2 ) ; dvd. on ( ) ; dvd. play ( movie) ; game. off ( ) ; } void playGame ( const std:: string& gameName) { std:: cout << "\n=== 开始游戏 ===" << std:: endl; screen. on ( ) ; screen. setInput ( 2 ) ; light. on ( ) ; speaker. on ( ) ; speaker. setMode ( 1 ) ; dvd. off ( ) ; game. on ( ) ; game. loadGame ( gameName) ; } void shutdown ( ) { std:: cout << "\n=== 系统关闭 ===" << std:: endl; screen. off ( ) ; light. off ( ) ; speaker. off ( ) ; dvd. off ( ) ; game. off ( ) ; }
} ;
客户端调用示例
int main ( ) { HomeTheaterFacade theater; theater. watchMovie ( "《阿凡达2》" ) ; theater. playGame ( "《塞尔达传说》" ) ; theater. shutdown ( ) ; return 0 ;
}
模式总结
核心原则
原则 说明 迪米特法则 一个对象应只与直接朋友交互,降低系统耦合 最少知识原则 客户端只需了解外观类,无需知道子系统细节
适用场景
子系统复杂 :存在多个独立子系统需要统一入口分层架构 :需要为不同层次提供统一接口第三方库 :封装底层API供上层调用
模式优缺点
优点 缺点 简化客户端调用 可能增加外观类复杂度 降低子系统耦合 不符合开闭原则(修改外观类) 提高系统可维护性