设计模式之外观模式

外观模式是一种结构型设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用。它可以简化复杂系统的使用,降低客户端与子系统之间的耦合度。

使用场景

  1. 简化客户端接口
    当你有一个复杂的系统,包含多个子系统或类时,可以使用外观模式为客户端提供一个简单的接口,隐藏系统的复杂性

    示例:在一个视频转换应用中,视频解码、音频处理、格式转换等操作都很复杂,使用外观模式提供一个统一的接口简化这些操作。

  2. 减少客户端与多个子系统之间的耦合
    外观模式将客户端与多个子系统解耦,使得客户端只需要与外观类交互,而不需要直接调用子系统的接口。

    示例:在一个电商系统中,订单处理涉及库存管理、支付处理、物流管理等子系统,使用外观模式提供一个订单处理接口,简化客户端的操作

  3. 层次化系统
    当一个系统需要层次化设计时,可以使用外观模式定义子系统的入口点,使得每个子系统的使用更加明确。

    示例:在一个大型软件系统中,不同的模块(如用户管理、权限管理、日志管理)可以分别定义外观类,提供统一的接口供其他模块调用。

UML类图

+-------------------+
|      Facade       |
+-------------------+
| +operation()      |
+-------------------+
         |
         |
  +------+------+--------+
  |             |        |
+------+   +------+   +------+
| Sub1 |   | Sub2 |   | Sub3 |
+------+   +------+   +------+
| +op()|   | +op()|   | +op()|
+------+   +------+   +------+

代码示例

假设我们有一个复杂的家庭影院系统,包括音响系统、投影仪、DVD播放器等,我们用外观模式来简化这些设备的操作。

#include <iostream>

// 子系统类:音响系统
class Amplifier {
public:
    void on() { std::cout << "Amplifier on" << std::endl; }
    void off() { std::cout << "Amplifier off" << std::endl; }
    void setVolume(int level) { std::cout << "Setting volume to " << level << std::endl; }
};

// 子系统类:投影仪
class Projector {
public:
    void on() { std::cout << "Projector on" << std::endl; }
    void off() { std::cout << "Projector off" << std::endl; }
    void setInput(const std::string& input) { std::cout << "Setting input to " << input << std::endl; }
};

// 子系统类:DVD播放器
class DVDPlayer {
public:
    void on() { std::cout << "DVDPlayer on" << std::endl; }
    void off() { std::cout << "DVDPlayer off" << std::endl; }
    void play(const std::string& movie) { std::cout << "Playing movie: " << movie << std::endl; }
};

// 外观类:家庭影院外观
class HomeTheaterFacade {
public:
    HomeTheaterFacade(Amplifier* amp, Projector* proj, DVDPlayer* dvd)
        : amp_(amp), proj_(proj), dvd_(dvd) {}

    void watchMovie(const std::string& movie) {
        std::cout << "Get ready to watch a movie..." << std::endl;
        amp_->on();
        amp_->setVolume(10);
        proj_->on();
        proj_->setInput("DVD");
        dvd_->on();
        dvd_->play(movie);
    }

    void endMovie() {
        std::cout << "Shutting down the movie theater..." << std::endl;
        dvd_->off();
        proj_->off();
        amp_->off();
    }

private:
    Amplifier* amp_;
    Projector* proj_;
    DVDPlayer* dvd_;
};

// 客户端代码
int main() {
    Amplifier amp;
    Projector proj;
    DVDPlayer dvd;

    HomeTheaterFacade homeTheater(&amp, &proj, &dvd);
    homeTheater.watchMovie("Inception");
    homeTheater.endMovie();

    return 0;
}

代码解读

  1. 子系统类(Amplifier, Projector, DVDPlayer)

    • 职责:实现各自的功能,如打开、关闭、设置参数等。
    • 方法
      • Amplifier 提供了 on, off, setVolume 方法。
      • Projector 提供了 on, off, setInput 方法。
      • DVDPlayer 提供了 on, off, play 方法。
  2. 外观类(HomeTheaterFacade)

    • 职责:提供一个简单的接口,封装子系统的复杂操作。
    • 方法
      • watchMovie:打开家庭影院系统并播放电影。
      • endMovie:关闭家庭影院系统。
  3. 客户端代码

    • 创建子系统对象 Amplifier, Projector, DVDPlayer
    • 创建外观对象 HomeTheaterFacade 并传入子系统对象。
    • 调用外观对象的 watchMovieendMovie 方法,简化了对家庭影院系统的操作。

优点

  1. 简化客户端接口
    客户端代码只需与外观类交互,不需要了解子系统的复杂接口,简化了客户端的使用。

  2. 降低客户端与子系统的耦合度
    客户端与子系统之间通过外观类进行交互,降低了耦合度,使得子系统的变化不会直接影响客户端。

  3. 更好的分层设计
    外观模式可以使得子系统与客户端之间的交互更加明确,有助于分层设计和模块化。

缺点

  1. 可能增加系统复杂性
    如果子系统本身已经很简单,引入外观模式可能会增加不必要的复杂性。

  2. 不符合开闭原则
    如果需要改变子系统的行为,可能需要修改外观类,违背了开闭原则(对扩展开放,对修改关闭)。

使用场景总结

  1. 简化客户端接口:如复杂系统中的多个子系统接口。
  2. 减少客户端与多个子系统之间的耦合:如电商系统中的订单处理。
  3. 层次化系统:如大型软件系统中不同模块的统一接口。

通过这个例子和解释,可以看到外观模式在简化接口、降低耦合和分层设计方面的强大功能。

  • 26
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值