计划模式-外观模式

[复制链接]
发表于 2025-6-21 18:23:11 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
外观模式

外观模式 (Facade Pattern) 是一种结构型计划模式,它为子体系中的一组接口提供一个同一的高层接口,使得子体系更轻易使用。
焦颔首脑:
想象一下你去看电影。你只需要告诉售票员你想看哪部电影,支付费用,然后拿到票。你不需要关心电影院内部复杂的运作流程,好比排片体系、票务打印体系、座位分配体系、财务体系等等。售票员(或者自助售票机)就饰演了一个“外观”的脚色,它简化了你与整个电影院子体系交互的过程。
外观模式就是这样,它隐藏了体系的复杂性,并向客户端提供了一个简化的接口。
模式结构:
外观模式通常包含以下脚色:

  • 外观 (Facade)

    • 知道哪些子体系类负责处理请求。
    • 将客户端的请求委派给恰当的子体系对象。
    • 它本身不包含业务逻辑,而是充当子体系的“包装器”或“中介”。
    • 为客户端提供一个单一、简化的入口点。

  • 子体系类 (Subsystem Classes)

    • 实现子体系的功能
    • 处理由 Facade 对象委派的任务。
    • 对 Facade 一无所知,即它们不持有 Facade 的引用。
    • 可以有多个子体系类,每个类负责一部分功能

  • 客户端 (Client)

    • 通过 Facade 接口与子体系举行交互。
    • 不需要了解子体系的内部结构和复杂性。

示意图:
  1. +----------------+     uses     +---------------------+
  2. |    Client      |------------->|       Facade        |
  3. +----------------+              +---------------------+
  4.                                     |
  5.                                     | delegates to
  6.                                     v
  7.                  +------------------+------------------+
  8.                  |                                     |
  9.        +-----------------+  +-----------------+  +-----------------+
  10.        | SubsystemClassA |  | SubsystemClassB |  | SubsystemClassC |
  11.        +-----------------+  +-----------------+  +-----------------+
复制代码
长处:

  • 低落耦合度 (Decoupling)

    • 客户端与子体系解耦:客户端只需要与 Facade 交互,不需要直接依赖于浩繁的子体系类。当子体系内部发生变化时,只要 Facade 的接口不变,客户端代码就不需要修改。
    • 子体系之间的解耦 (某种程度上):虽然 Facade 本身大概会耦合多个子体系,但它提供了一个单一的入口,有助于管理这些依赖。如果计划恰当,子体系之间也可以通过 Facade 间接交互,而不是直接依赖。

  • 简化接口 (Simplifies Interface):Facade 提供了一个更高层次的、更简单的接口,使得子体系更轻易被使用。客户端不需要了解子体系中各个类的复杂关系和调用次序。
  • 提高可维护性 (Improved Maintainability):当子体系发生变化时,只需要修改 Facade 或子体系内部,而客户端代码通常不受影响。
  • 更好的分层 (Better Layering):Facade 可以资助构建分层体系,Facade 作为服务层,为表现层或业务逻辑层提供同一的访问接口。
  • 易于理解和使用 (Easier to Understand and Use):对于新的开发者来说,通过 Facade 接口可以更快地了解如何使用一个复杂的子体系。
缺点:

  • 大概产生“上帝对象” (God Object):如果 Facade 承担了过多的责任,或者包装了太多的子体系功能,它本身大概会变得非常巨大和复杂,违反单一职责原则。
  • 不符合开闭原则 (Against Open/Closed Principle):当需要为子体系增长新的功能时,大概需要修改 Facade 类的源代码,这违反了开闭原则(对扩睁开放,对修改关闭)。固然,可以通过引入其他模式(如装饰器模式或计谋模式)来缓解这个题目。
  • 不能完全隐藏复杂性:Facade 只是提供了一个简化的接口,如果客户端需要更底层的、更机动的控制,它仍然可以直接访问子体系类(如果子体系类是可见的)。Facade 并不制止这种直接访问。
适用场景:

  • 为一个复杂的子体系提供一个简单的接口:当一个体系非常复杂,或者其内部细节难以理解时,可以使用 Facade 来简化客户端的调用。
  • 需要将客户端与子体系的实现解耦:当希望淘汰客户端与子体系内部类的依赖关系,以便将来可以独立地修改子体系时。
  • 构建分层结构:当需要为体系界说清楚的层次,Facade 可以作为某一层(如服务层)的入口。
  • 包装遗留代码或第三方库:当需要与一个计划不佳或者接口复杂的遗留体系或第三方库集成时,可以使用 Facade 来提供一个更清楚、更符合当前体系计划风格的接口。
代码示例 (Java):
假设我们有一个家庭影院体系,包含 DVD 播放器、投影仪、音响、灯光等子体系。
子体系类:
  1. // 子系统类
  2. class DvdPlayer {
  3.    public void on() { System.out.println("DVD Player on"); }
  4.    public void off() { System.out.println("DVD Player off"); }
  5.    public void play(String movie) { System.out.println("DVD Player playing "" + movie + """); }
  6.    public void stop() { System.out.println("DVD Player stopped"); }
  7.    public void eject() { System.out.println("DVD Player eject"); }
  8. }
  9. class Projector {
  10.    public void on() { System.out.println("Projector on"); }
  11.    public void off() { System.out.println("Projector off"); }
  12.    public void wideScreenMode() { System.out.println("Projector in widescreen mode (16x9 aspect ratio)"); }
  13. }
  14. class Amplifier {
  15.    public void on() { System.out.println("Amplifier on"); }
  16.    public void off() { System.out.println("Amplifier off"); }
  17.    public void setDvd(DvdPlayer dvd) { System.out.println("Amplifier setting DVD player"); }
  18.    public void setSurroundSound() { System.out.println("Amplifier surround sound on (5.1 channels)"); }
  19.    public void setVolume(int level) { System.out.println("Amplifier setting volume to " + level); }
  20. }
  21. class TheaterLights {
  22.    public void on() { System.out.println("Theater lights on"); }
  23.    public void off() { System.out.println("Theater lights off"); }
  24.    public void dim(int level) { System.out.println("Theater lights dimming to " + level + "%"); }
  25. }
  26. // ... 其他子系统如 PopcornPopper, Screen 等
复制代码
外观类 (Facade):
  1. class HomeTheaterFacade {
  2.    private DvdPlayer dvd;
  3.    private Projector projector;
  4.    private Amplifier amp;
  5.    private TheaterLights lights;
  6.    public HomeTheaterFacade(DvdPlayer dvd, Projector projector, Amplifier amp, TheaterLights lights) {
  7.        this.dvd = dvd;
  8.        this.projector = projector;
  9.        this.amp = amp;
  10.        this.lights = lights;
  11.    }
  12.    public void watchMovie(String movie) {
  13.        System.out.println("Get ready to watch a movie...");
  14.        lights.dim(10);
  15.        projector.on();
  16.        projector.wideScreenMode();
  17.        amp.on();
  18.        amp.setDvd(dvd);
  19.        amp.setSurroundSound();
  20.        amp.setVolume(5);
  21.        dvd.on();
  22.        dvd.play(movie);
  23.    }
  24.    public void endMovie() {
  25.        System.out.println("Shutting movie theater down...");
  26.        dvd.stop();
  27.        dvd.eject();
  28.        dvd.off();
  29.        amp.off();
  30.        projector.off();
  31.        lights.on();
  32.    }
  33. }
复制代码
客户端代码:
  1. public class HomeTheaterTestDrive {
  2.    public static void main(String[] args) {
  3.        // 初始化子系统
  4.        DvdPlayer dvd = new DvdPlayer();
  5.        Projector projector = new Projector();
  6.        Amplifier amp = new Amplifier();
  7.        TheaterLights lights = new TheaterLights();
  8.        // 创建外观
  9.        HomeTheaterFacade homeTheater = new HomeTheaterFacade(dvd, projector, amp, lights);
  10.        // 使用外观的简化接口
  11.        homeTheater.watchMovie("Raiders of the Lost Ark");
  12.        System.out.println("\n--- Movie ended, let's turn it off ---\n");
  13.        homeTheater.endMovie();
  14.    }
  15. }
复制代码
在这个例子中,HomeTheaterFacade 封装了启动和关闭家庭影院所需的一系列复杂操纵。客户端只需要调用 watchMovie() 和 endMovie() 这样简单的方法,而不需要关心各个装备的具体操纵次序和细节。
与迪米特法则的关系:
外观模式通常有助于遵照迪米特法则。客户端只与 Facade 对象交互(直接朋友),而不需要了解 Facade 内部所依赖的子体系(朋友的朋友)。Facade 自身大概会与多个子体系交互,但从客户端的角度来看,交互点被简化了。
总而言之,外观模式是一个非常有用的模式,当你想要简化复杂体系的使用,或者隔离变化时,它是一个值得考虑的选择。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5

GMT+8, 2025-7-21 20:23 , Processed in 0.267516 second(s), 35 queries 手机版|qidao123.com技术社区-IT企服评测▪应用市场 ( 浙ICP备20004199 )|网站地图

快速回复 返回顶部 返回列表