设计模式 10 外观模式

设计模式 10

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

外观模式(Facade Pattern)

1 定义

外观模式通过为复杂的子系统提供一个简化的接口,使得客户端可以通过这个接口访问子系统的功能,而不需要直接与子系统的多个组件进行交互。外观模式可以隐藏子系统的复杂性,并且使得子系统与客户端的耦合度降低。

2 结构

外观模式的结构包含以下角色:

  • 外观(Facade): 提供一个简化的接口,封装子系统的复杂性,供客户端调用。
  • 子系统(Subsystem Classes): 子系统中的多个类,它们实现了子系统的实际功能。子系统可以有多个类,客户端可以直接访问它们,但通过外观类访问会更简单。

UML 类图

                            +-------------------+
                            |      Client       |
                            +-------------------+
                                     ^
                                     |
+-------------------+       +-------------------+       +-------------------+
|    SubsystemA     | ----> |      Facade       | <---- |    SubsystemC     |
+-------------------+       +-------------------+       +-------------------+
                                     ^                           ^
                                     |                           |
                            +-------------------+       +-------------------+
                            |    SubsystemB     |       |    SubsystemD     |
                            +-------------------+       +-------------------+

3 示例代码

以下是一个实现外观模式的简单示例。在这个示例中,我们构建了一个家庭影院系统,客户端通过外观类 HomeTheaterFacade 来控制各个子系统,如电视、音响、灯光等。

子系统类

// 子系统类:电视
public class Television
{
    public void On()
    {
        Console.WriteLine("Television is on.");
    }

    public void Off()
    {
        Console.WriteLine("Television is off.");
    }
}

// 子系统类:音响
public class SoundSystem
{
    public void On()
    {
        Console.WriteLine("Sound system is on.");
    }

    public void Off()
    {
        Console.WriteLine("Sound system is off.");
    }

    public void SetVolume(int volume)
    {
        Console.WriteLine($"Sound system volume set to {volume}.");
    }
}

// 子系统类:灯光
public class Lights
{
    public void Dim(int level)
    {
        Console.WriteLine($"Lights dimmed to {level}%.");
    }

    public void On()
    {
        Console.WriteLine("Lights are on.");
    }
}

外观类

// 外观类:家庭影院
public class HomeTheaterFacade
{
    private readonly Television _television;
    private readonly SoundSystem _soundSystem;
    private readonly Lights _lights;

    public HomeTheaterFacade(Television television, SoundSystem soundSystem, Lights lights)
    {
        _television = television;
        _soundSystem = soundSystem;
        _lights = lights;
    }

    public void WatchMovie()
    {
        Console.WriteLine("Get ready to watch a movie...");
        _lights.Dim(30);
        _television.On();
        _soundSystem.On();
        _soundSystem.SetVolume(5);
    }

    public void EndMovie()
    {
        Console.WriteLine("Shutting movie theater down...");
        _television.Off();
        _soundSystem.Off();
        _lights.On();
    }
}

客户端代码

class Program
{
    static void Main(string[] args)
    {
        // 创建子系统对象
        Television television = new Television();
        SoundSystem soundSystem = new SoundSystem();
        Lights lights = new Lights();

        // 创建外观对象
        HomeTheaterFacade homeTheater = new HomeTheaterFacade(television, soundSystem, lights);

        // 使用外观模式控制子系统
        homeTheater.WatchMovie();
        Console.WriteLine("\nMovie is running...\n");
        homeTheater.EndMovie();
    }
}

在这个例子中:

  • TelevisionSoundSystemLights 是子系统类,提供了各自的功能。
  • HomeTheaterFacade 是外观类,它将各个子系统的操作封装成了 WatchMovie()EndMovie() 两个简单的方法,客户端只需调用这些方法即可控制整个家庭影院系统。
  • 客户端 Program 通过 HomeTheaterFacade 类来控制整个家庭影院的各个设备,而不需要直接与每个设备交互。

4 特点

  • 优点:

    • 简化接口: 提供一个简化的接口来访问复杂的子系统,减少客户端与子系统之间的耦合。

    • 隐藏子系统的复杂性: 客户端不需要了解子系统的内部结构,只需要与外观类交互即可。

    • 减少依赖: 客户端与子系统之间的依赖关系减少,如果子系统发生变化,只需修改外观类,而不需要修改客户端代码。

  • 缺点:

    • 不符合开闭原则: 如果要扩展外观类的功能,可能需要修改外观类的代码,从而违反开闭原则。

    • 潜在性能问题: 外观模式可能会因为封装了大量子系统的调用,而引入一定的性能开销。

5 适用场景

  • 简化复杂系统的使用: 当系统内部结构复杂,客户端希望能够通过简单的接口使用系统时,使用外观模式非常合适。
  • 解耦客户端与子系统: 当你希望减少客户端与多个子系统之间的依赖关系时,可以使用外观模式。
  • 构建库或框架: 当你构建一个复杂库或框架,并希望提供一个简洁的接口供外部使用时,外观模式可以帮助你设计这个接口。

6 与其他模式的关系

  • 与适配器模式的区别: 适配器模式是为了将一个接口转换为客户端期望的接口,而外观模式是为了提供一个简化的接口来使用复杂系统。适配器模式专注于接口兼容性,而外观模式专注于简化系统的使用。
  • 与桥接模式的区别: 桥接模式用于将抽象与实现分离,使得它们可以独立变化,而外观模式关注于简化接口。
  • 与单例模式的结合: 在某些情况下,外观类可以设计成单例,以确保客户端使用的是同一个外观对象。

外观模式通过提供一个统一和简化的接口来隐藏系统的复杂性,使得客户端能够更轻松地使用系统,同时保持系统内部结构的灵活性和可扩展性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WineMonk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值