定义
外观模式 (Facade Pattern) 是一种结构型设计模式,它为子系统中的一组接口提供一个统一的高层接口。这个接口使得子系统更容易使用。
基本结构
-
外观类 (Facade):提供简化的接口,内部协调多个子系统
-
子系统类 (Subsystem):实现具体的业务逻辑
-
客户端 (Client):通过外观类来使用子系统
(1)代码模板
c#
// 1. 创建子系统类
class A { public void DoA() {} }
class B { public void DoB() {} }
class C { public void DoC() {} }
// 2. 创建外观类
class Facade
{
private A _a = new A();
private B _b = new B();
private C _c = new C();
// 3. 提供简单方法
public void DoAll()
{
_a.DoA();
_b.DoB();
_c.DoC();
}
}
// 4. 客户端使用
Facade facade = new Facade();
facade.DoAll(); // 一行代替三行
(2)简单示例:智能家居系统
下面是用 C# 实现的外观模式 示例项目,以智能家居控制系统为应用场景。
c#
namespace 外观模式
{
// 子系统组件1:灯光
class Light
{
public void TurnOn()
{
Console.WriteLine("客厅灯已打开");
}
public void TurnOff()
{
Console.WriteLine("客厅灯已关闭");
}
public void SetBrightness(int level)
{
Console.WriteLine($"灯光亮度设置为: {level}%");
}
}
// 子系统组件2:空调
class AirConditioner
{
public void TurnOn()
{
Console.WriteLine("空调已打开");
}
public void TurnOff()
{
Console.WriteLine("空调已关闭");
}
public void SetTemperature(int temperature)
{
Console.WriteLine($"空调温度设置为: {temperature}°C");
}
}
// 子系统组件3:电视
class TV
{
public void TurnOn()
{
Console.WriteLine("电视已打开");
}
public void TurnOff()
{
Console.WriteLine("电视已关闭");
}
public void SetChannel(int channel)
{
Console.WriteLine($"切换到频道: {channel}");
}
public void SetVolume(int volume)
{
Console.WriteLine($"音量设置为: {volume}");
}
}
// 子系统组件4:音响
class SoundSystem
{
public void TurnOn()
{
Console.WriteLine("音响系统已打开");
}
public void TurnOff()
{
Console.WriteLine("音响系统已关闭");
}
public void SetVolume(int volume)
{
Console.WriteLine($"音响音量设置为: {volume}");
}
public void PlayMusic()
{
Console.WriteLine("播放音乐...");
}
}
// 外观类:提供简化的接口
class SmartHomeFacade
{
private Light light;
private AirConditioner airConditioner;
private TV tv;
private SoundSystem soundSystem;
public SmartHomeFacade()
{
light = new Light();
airConditioner = new AirConditioner();
tv = new TV();
soundSystem = new SoundSystem();
}
// 场景1:回家模式
public void ComeHome()
{
Console.WriteLine("========== 执行回家模式 ==========");
light.TurnOn();
light.SetBrightness(80);
airConditioner.TurnOn();
airConditioner.SetTemperature(24);
tv.TurnOn();
tv.SetChannel(1);
tv.SetVolume(30);
Console.WriteLine("=================================\n");
}
// 场景2:离家模式
public void LeaveHome()
{
Console.WriteLine("========== 执行离家模式 ==========");
light.TurnOff();
airConditioner.TurnOff();
tv.TurnOff();
soundSystem.TurnOff();
Console.WriteLine("=================================\n");
}
// 场景3:观影模式
public void WatchMovie()
{
Console.WriteLine("========== 执行观影模式 ==========");
light.TurnOn();
light.SetBrightness(20);
tv.TurnOn();
tv.SetChannel(5);
tv.SetVolume(25);
soundSystem.TurnOn();
soundSystem.SetVolume(40);
airConditioner.TurnOn();
airConditioner.SetTemperature(22);
Console.WriteLine("=================================\n");
}
// 场景4:睡眠模式
public void Sleep()
{
Console.WriteLine("========== 执行睡眠模式 ==========");
light.TurnOff();
tv.TurnOff();
soundSystem.TurnOff();
airConditioner.TurnOn();
airConditioner.SetTemperature(26);
Console.WriteLine("=================================\n");
}
}
class Program
{
static void Main(string[] args)
{
// 创建外观对象
SmartHomeFacade smartHome = new SmartHomeFacade();
// 使用简化的接口来控制智能家居
smartHome.ComeHome(); // 回家
smartHome.WatchMovie(); // 看电影
smartHome.Sleep(); // 睡觉
smartHome.LeaveHome(); // 离家
Console.WriteLine("\n如果不使用外观模式,需要逐个调用各个子系统的方法:");
Console.WriteLine("================================================================\n");
// 对比:不使用外观模式的情况
Light directLight = new Light();
AirConditioner directAC = new AirConditioner();
TV directTV = new TV();
// 客户端需要知道所有子系统的细节
directLight.TurnOn();
directLight.SetBrightness(100);
directAC.TurnOn();
directAC.SetTemperature(25);
directTV.TurnOn();
directTV.SetChannel(3);
directTV.SetVolume(35);
}
}
}
效果展示:
bash
Hello, World!
========== 执行回家模式 ==========
客厅灯已打开
灯光亮度设置为: 80%
空调已打开
空调温度设置为: 24°C
电视已打开
切换到频道: 1
音量设置为: 30
=================================
========== 执行观影模式 ==========
客厅灯已打开
灯光亮度设置为: 20%
电视已打开
切换到频道: 5
音量设置为: 25
音响系统已打开
音响音量设置为: 40
空调已打开
空调温度设置为: 22°C
=================================
========== 执行睡眠模式 ==========
客厅灯已关闭
电视已关闭
音响系统已关闭
空调已打开
空调温度设置为: 26°C
=================================
========== 执行离家模式 ==========
客厅灯已关闭
空调已关闭
电视已关闭
音响系统已关闭
=================================
如果不使用外观模式,需要逐个调用各个子系统的方法:
================================================================
客厅灯已打开
灯光亮度设置为: 100%
空调已打开
空调温度设置为: 25°C
电视已打开
切换到频道: 3
音量设置为: 35
-
使用外观模式前:客户端需要逐个调用7+个方法,必须了解每个子系统的细节。
-
使用外观模式后:客户端只需调用1个方法(如 smartHome.ComeHome() ),无需知道内部实现细节。
这种模式降低了系统的耦合度,提高了代码的可维护性和易用性。
适用场景
✅ 系统越来越复杂,客户端需要简化的接口
✅ 客户端与多个子系统之间存在大量依赖关系
✅ 需要分层架构,定义每一层的入口
✅ 为遗留系统创建新的接口
优缺点
- 优点:
降低客户端使用复杂度
减少客户端与子系统之间的耦合
提高代码的可维护性和可读性
不影响客户端直接使用子系统
- 缺点:
可能增加不必要的外观类
不符合开闭原则(修改子系统可能需要修改外观类)
- 现实生活中的例子
智能家居的一键模式
电脑开机(CPU、内存、硬盘、显示器协同工作)
银行转账(验证账户、检查余额、扣款、入账、通知)