【软考设计模式】外观模式:复杂子系统的“门面“封装与代码填空精讲

系列定位:软考软件设计师 / 系统架构设计师 --- 结构型模式专题第 4 讲

考察分值:上午题 1-2 分,下午题常作为代码填空或类图识别出现

难度等级:⭐⭐☆☆☆(概念最直观,但与其他模式的辨析是失分点)


一、考纲定位与模式定义

1.1 考纲要求

外观模式在软考中属于 结构型模式 的入门内容。考察形式包括:

  • 上午选择题:判断场景描述所属模式;识别外观模式与适配器模式、代理模式的区别;判断外观类是否屏蔽了子系统的内部细节

  • 下午设计题:补全 Facade 类中对多个子系统方法的调用顺序;补全客户端通过 Facade 调用而非直接调用子系统的代码;识别类图中 Facade 与子系统之间的依赖/关联关系

1.2 模式定义

外观模式:为子系统中的一组接口提供一个统一的高层接口,这个接口使得子系统更加容易使用。

核心意图 :当一个子系统由多个类组成,且这些类的调用顺序复杂、相互依赖时,客户端直接与子系统交互的成本很高(需要了解每个子系统类的接口、调用顺序、依赖关系)。外观模式引入一个 "门面"(Facade) 类,将子系统的复杂调用逻辑封装在 Facade 内部,客户端只需与 Facade 打交道,无需关心子系统的内部细节。

通俗理解

你去餐厅吃饭,后厨有切配、炒菜、装盘、传菜等多个岗位(子系统)。作为顾客(客户端),你不需要跑到后厨指挥每个岗位 "先切配、再炒菜、再装盘",你只需要对服务员(Facade)说 "来一份宫保鸡丁",服务员 internally 协调后厨完成所有步骤,最终把菜端给你。服务员就是后厨子系统的 "门面"。

关键原则 :外观模式不阻止客户端直接访问子系统,只是提供了一个 更简单的入口。如果客户端需要更细粒度的控制,仍然可以直接调用子系统类。


二、UML 类图与角色划分

复制代码
┌─────────────────────────────────────────────────────────┐
│                      Client                             │
│  + main()                                               │
│    ├── Facade facade = new Facade();                    │
│    └── facade.doSomething();  // 一键调用,无需关心内部     │
└───────────────────────┬─────────────────────────────────┘
                        │ uses
                        ▼
┌─────────────────────────────────────────────────────────┐
│                    Facade                               │
│  ── 门面类:封装子系统的复杂调用逻辑 ──                      │
│  - subA: SubsystemA                                     │
│  - subB: SubsystemB                                     │
│  - subC: SubsystemC                                     │
│  + doSomething() {                                      │
│      subA.operationA();                                 │
│      subB.operationB();                                 │
│      subC.operationC();                                 │
│    }                                                    │
└───────────────────────┬─────────────────────────────────┘
           ┌────────────┼────────────┐
           ▼            ▼            ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│  SubsystemA     │ │  SubsystemB     │ │  SubsystemC     │
│  + operationA() │ │  + operationB() │ │  + operationC() │
│    (子系统A)     │ │    (子系统B)     │ │    (子系统C)     │
└─────────────────┘ └─────────────────┘ └─────────────────┘
角色 职责 软考填空关键词
Facade(外观) 封装子系统的复杂调用逻辑,提供一个简洁的高层接口 class + 组合多个子系统引用 + 统一方法
Subsystem(子系统) 子系统内部的各个类,完成具体的子功能 多个独立的类,各自有特定方法
Client(客户端) 通过 Facade 访问子系统,不直接与子系统类交互 new Facade() + facade.method()

类图识别要点 :软考类图中,外观模式的核心特征是存在一个 Facade 类,它同时与多个子系统类有关联/依赖关系(箭头从 Facade 指向多个 Subsystem),而 Client 只与 Facade 交互。如果类图里只有一个类连接多个子系统,且 Client 不直接连子系统 → 外观。如果 Client 直接连子系统,且有一个类做接口转换 → 适配器。


三、场景一:家庭影院一键观影(最经典的外观模式)

业务背景:家庭影院子系统包含多个设备:投影仪(Projector)、音响(SoundSystem)、播放器(DVDPlayer)、灯光(Light)。要看一场电影,需要按顺序操作:关灯 → 放下幕布 → 打开投影仪 → 打开音响 → 放入光盘 → 播放。如果客户端直接操作每个设备,调用顺序复杂且容易出错。使用外观模式封装 "一键观影" 流程。

说明:这是外观模式最经典的例子,也是软考下午题最爱考的 "将多个子系统调用封装为一个方法" 场景。

3.1 代码实现
java 复制代码
// Subsystem:投影仪
public class Projector {
    public void on() {
        System.out.println("投影仪:开启");
    }
    public void setInput(String input) {
        System.out.println("投影仪:切换到 " + input + " 输入源");
    }
    public void off() {
        System.out.println("投影仪:关闭");
    }
}

// Subsystem:音响系统
public class SoundSystem {
    public void on() {
        System.out.println("音响:开启");
    }
    public void setVolume(int level) {
        System.out.println("音响:音量调至 " + level);
    }
    public void off() {
        System.out.println("音响:关闭");
    }
}

// Subsystem:DVD 播放器
public class DVDPlayer {
    public void on() {
        System.out.println("DVD 播放器:开启");
    }
    public void play(String movie) {
        System.out.println("DVD 播放器:开始播放《" + movie + "》");
    }
    public void off() {
        System.out.println("DVD 播放器:关闭");
    }
}

// Subsystem:灯光控制
public class Light {
    public void dim() {
        System.out.println("灯光:调暗");
    }
    public void bright() {
        System.out.println("灯光:调亮");
    }
}

// Subsystem:幕布
public class Screen {
    public void down() {
        System.out.println("幕布:放下");
    }
    public void up() {
        System.out.println("幕布:收起");
    }
}

// Facade:家庭影院外观
public class HomeTheaterFacade {
    private Projector projector;
    private SoundSystem sound;
    private DVDPlayer dvd;
    private Light light;
    private Screen screen;
    
    public HomeTheaterFacade(Projector projector, SoundSystem sound,
                             DVDPlayer dvd, Light light, Screen screen) {
        this.projector = projector;
        this.sound = sound;
        this.dvd = dvd;
        this.light = light;
        this.screen = screen;
    }
    
    public void watchMovie(String movie) {
        System.out.println("===== 准备观影 =====");
        light.dim();
        screen.down();
        projector.on();
        projector.setInput("DVD");
        sound.on();
        sound.setVolume(20);
        dvd.on();
        dvd.play(movie);
        System.out.println("===== 开始观影 =====\n");
    }
    
    public void endMovie() {
        System.out.println("===== 结束观影 =====");
        dvd.off();
        sound.off();
        projector.off();
        screen.up();
        light.bright();
        System.out.println("===== 已恢复 =====\n");
    }
}

// Client:客户端
public class Client {
    public static void main(String[] args) {
        HomeTheaterFacade theater = new HomeTheaterFacade(
            new Projector(),
            new SoundSystem(),
            new DVDPlayer(),
            new Light(),
            new Screen()
        );
        
        theater.watchMovie("星际穿越");
        theater.endMovie();
    }
}

关键体会watchMovie() 方法内部封装了 6 个子系统调用,按固定顺序执行。客户端只需调用 watchMovie("星际穿越"),完全不需要知道投影仪、音响、DVD 等子系统的存在。这就是 "门面" 的价值 ------ 简化接口,降低耦合


四、场景二:电商订单处理系统(业务子系统封装)

业务背景:电商系统下单流程涉及多个子系统:库存检查(Inventory)、支付处理(Payment)、物流下单(Shipping)、邮件通知(Notification)。一个完整的下单流程需要:检查库存 → 扣减库存 → 处理支付 → 创建物流单 → 发送确认邮件。使用外观模式封装 "一键下单" 流程。

说明:这是软考下午题中常见的 "业务流程封装" 场景,Facade 的方法对应一个完整的业务流程。

4.1 代码实现

java

java 复制代码
// Subsystem:库存系统
public class InventoryService {
    public boolean checkStock(String productId, int quantity) {
        System.out.println("[库存] 检查商品 " + productId + " 库存,数量: " + quantity);
        return true;
    }
    
    public void deductStock(String productId, int quantity) {
        System.out.println("[库存] 扣减商品 " + productId + " 库存 " + quantity + " 件");
    }
    
    public void restoreStock(String productId, int quantity) {
        System.out.println("[库存] 恢复商品 " + productId + " 库存 " + quantity + " 件");
    }
}

// Subsystem:支付系统
public class PaymentService {
    public boolean processPayment(String orderId, double amount) {
        System.out.println("[支付] 处理订单 " + orderId + " 支付,金额: ¥" + amount);
        return true;
    }
    
    public void refund(String orderId) {
        System.out.println("[支付] 订单 " + orderId + " 退款完成");
    }
}

// Subsystem:物流系统
public class ShippingService {
    public String createShippingOrder(String orderId, String address) {
        String trackingNo = "SF" + System.currentTimeMillis();
        System.out.println("[物流] 创建运单,订单: " + orderId + ", 单号: " + trackingNo);
        return trackingNo;
    }
}

// Subsystem:通知系统
public class NotificationService {
    public void sendOrderConfirmation(String email, String orderId) {
        System.out.println("[通知] 发送订单确认邮件到 " + email + ",订单号: " + orderId);
    }
}

// Facade:订单处理外观
public class OrderFacade {
    private InventoryService inventory;
    private PaymentService payment;
    private ShippingService shipping;
    private NotificationService notification;
    
    public OrderFacade() {
        this.inventory = new InventoryService();
        this.payment = new PaymentService();
        this.shipping = new ShippingService();
        this.notification = new NotificationService();
    }
    
    public boolean placeOrder(String productId, int quantity, 
                               double amount, String email, String address) {
        String orderId = "ORD" + System.currentTimeMillis();
        
        try {
            if (!inventory.checkStock(productId, quantity)) {
                System.out.println("下单失败:库存不足");
                return false;
            }
            
            inventory.deductStock(productId, quantity);
            
            if (!payment.processPayment(orderId, amount)) {
                inventory.restoreStock(productId, quantity);
                System.out.println("下单失败:支付未成功");
                return false;
            }
            
            String trackingNo = shipping.createShippingOrder(orderId, address);
            notification.sendOrderConfirmation(email, orderId);
            
            System.out.println("下单成功!订单号: " + orderId + ",运单号: " + trackingNo);
            return true;
            
        } catch (Exception e) {
            inventory.restoreStock(productId, quantity);
            System.out.println("下单失败:系统异常");
            return false;
        }
    }
}

// Client
public class Client {
    public static void main(String[] args) {
        OrderFacade orderFacade = new OrderFacade();
        
        boolean success = orderFacade.placeOrder(
            "SKU1001",
            2,
            599.0,
            "user@example.com",
            "北京市海淀区"
        );
    }
}

关键体会 :Facade 不仅封装了调用顺序,还处理了 异常回滚(支付失败时恢复库存)。这是实际开发中外观模式的常见用法 ------ Facade 作为一个 "事务协调者",保证子系统调用的一致性。


五、场景三:数据库操作外观(简化复杂 API)

业务背景 :JDBC 操作数据库需要多个步骤:加载驱动 → 获取连接 → 创建语句 → 执行 SQL → 处理结果集 → 关闭资源。使用外观模式封装常用的 CRUD 操作,让客户端只需调用 query()update() 即可。

说明:这是实际开发中外观模式的简化应用,也是软考上午题中 "简化 API" 场景的典型代表。

5.1 代码实现
java 复制代码
import java.sql.*;

// Facade:数据库操作外观
public class DatabaseFacade {
    private String url;
    private String user;
    private String password;
    
    public DatabaseFacade(String url, String user, String password) {
        this.url = url;
        this.user = user;
        this.password = password;
    }
    
    public ResultSet query(String sql) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = DriverManager.getConnection(url, user, password);
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            return rs;
        } catch (SQLException e) {
            throw new RuntimeException("查询失败", e);
        }
    }
    
    public int update(String sql) {
        try (Connection conn = DriverManager.getConnection(url, user, password);
             Statement stmt = conn.createStatement()) {
            return stmt.executeUpdate(sql);
        } catch (SQLException e) {
            throw new RuntimeException("更新失败", e);
        }
    }
    
    public boolean executeTransaction(String... sqls) {
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            conn.setAutoCommit(false);
            try (Statement stmt = conn.createStatement()) {
                for (String sql : sqls) {
                    stmt.executeUpdate(sql);
                }
                conn.commit();
                return true;
            } catch (SQLException e) {
                conn.rollback();
                return false;
            }
        } catch (SQLException e) {
            throw new RuntimeException("事务执行失败", e);
        }
    }
}

// Client
public class Client {
    public static void main(String[] args) {
        DatabaseFacade db = new DatabaseFacade(
            "jdbc:mysql://localhost:3306/test", "root", "123456"
        );
        
        int rows = db.update("UPDATE users SET status = 1 WHERE id = 1001");
        System.out.println("影响行数: " + rows);
        
        boolean ok = db.executeTransaction(
            "UPDATE account SET balance = balance - 100 WHERE id = 1",
            "UPDATE account SET balance = balance + 100 WHERE id = 2"
        );
        System.out.println("转账结果: " + ok);
    }
}

六、三种场景对比与演进思路

维度 场景一:家庭影院 场景二:电商下单 场景三:数据库操作
子系统数量 5 个(投影仪、音响、DVD、灯光、幕布) 4 个(库存、支付、物流、通知) 多个 JDBC 类(Connection、Statement、ResultSet)
Facade 职责 封装固定调用顺序 封装业务流程 + 异常回滚 封装复杂 API,简化调用
子系统创建方式 外部注入(构造器参数) Facade 内部创建 Facade 内部创建
是否有返回值 无(void) 有(boolean 成功/失败) 有(ResultSet、int)
异常处理 有(回滚库存、退款) 有(事务回滚)
Client 复杂度 极低(只需 1 个方法) 极低(只需 1 个方法) 极低(只需 1 个方法)
软考考法 下午大题(补全调用顺序) 下午大题(补全业务流程) 上午选择题(识别简化 API)

七、外观模式 vs 适配器模式 vs 代理模式:核心对比

对比项 外观模式 适配器模式 代理模式
设计目的 简化 子系统的使用,提供高层接口 转换 接口,兼容不兼容的类 控制 对象的访问(延迟加载、权限等)
接口变化 提供 新的高层 接口(封装多个子接口) 转换 已有接口为另一个接口 保持 原接口不变
子系统数量 通常涉及 多个 子系统类 通常涉及 一个 Adaptee 通常涉及 一个 RealSubject
Client 调用 只调用 Facade 调用 Adapter(Adapter 内部调用 Adaptee) 调用 Proxy(Proxy 内部调用 RealSubject)
是否隐藏子系统 部分隐藏(Client 可以选择直接访问子系统) 完全隐藏(Client 不知道 Adaptee) 完全透明(Client 以为在调用 RealSubject)
软考判断 一个类封装多个子系统的调用 一个类转换两个不同接口 一个类控制对另一个类的访问

记忆口诀:外观是 "简化入口"(封装复杂子系统),适配器是 "翻译官"(接口转换),代理是 "中间人"(控制访问)。


八、软考高频考点与易混淆辨析

8.1 高频考点
考点 内容
模式分类 结构型模式(GoF 23 正式成员)
核心角色 Facade(外观)、Subsystem(子系统,多个)、Client(客户端)
核心思想 为子系统提供 统一的高层接口,降低客户端与子系统的耦合
设计原则 最少知识原则(迪米特法则):客户端只需与 Facade 交互,不需要了解子系统内部
是否阻止直接访问 ❌ 不阻止。外观只是提供一个简化入口,客户端仍可直接访问子系统
与单例结合 外观类通常设计为 单例(整个系统只需要一个门面)
适用场景 ① 子系统复杂,客户端调用成本高 ② 需要分层架构(层与层之间通过外观交互)③ 需要解耦客户端与子系统
与中介者区别 外观:Client → Facade → Subsystem(单向,Facade 封装子系统);中介者:Colleague ↔ Mediator ↔ Colleague(双向,协调多个对等对象)
8.2 易混淆辨析:外观 vs 中介者
对比项 外观模式 中介者模式
交互方向 单向:Client → Facade → Subsystem 双向:Colleague ↔ Mediator ↔ Colleague
对象关系 Facade 封装 子系统(子系统不知道 Facade 的存在) Mediator 协调 对等对象(同事对象知道 Mediator 的存在)
目的 简化客户端对子系统的使用 解耦多个对象之间的相互引用
类图结构 Facade 依赖多个 Subsystem Mediator 与多个 Colleague 双向关联
软考判断 一个类封装多个子系统供客户端使用 一个类协调多个对等对象之间的交互

九、真题风格模拟与代码填空

模拟题 1(上午选择题)

以下关于外观模式的叙述中,正确的是()。

A. 外观模式属于创建型模式,主要用于创建子系统的统一入口

B. 在外观模式中,Facade 类通过继承子系统类来简化客户端调用

C. 外观模式为子系统中的一组接口提供一个统一的高层接口,使得子系统更加容易使用

D. 外观模式会阻止客户端直接访问子系统的内部类,强制所有调用必须通过 Facade

答案:C

解析

  • A 错误:外观属于 结构型 模式,不是创建型。

  • B 错误:Facade 通过 组合(持有子系统引用)来调用子系统,不是继承。外观模式不修改子系统的继承结构。

  • C 正确:这是外观模式的核心定义。

  • D 错误:外观模式 不阻止 客户端直接访问子系统。Facade 只是提供一个简化入口,如果客户端需要更细粒度的控制,仍然可以直接调用子系统类。


模拟题 2(下午代码填空 --- 补全外观类封装逻辑)

某系统使用外观模式封装编译子系统。编译流程包括:词法分析(Lexer)、语法分析(Parser)、代码生成(CodeGenerator)。请补全(1)~(4)。

java 复制代码
// Subsystem:词法分析
class Lexer {
    public String tokenize(String source) {
        System.out.println("词法分析完成");
        return "tokens";
    }
}

// Subsystem:语法分析
class Parser {
    public String parse(String tokens) {
        System.out.println("语法分析完成");
        return "ast";
    }
}

// Subsystem:代码生成
class CodeGenerator {
    public String generate(String ast) {
        System.out.println("代码生成完成");
        return "machine_code";
    }
}

// Facade:编译外观
class CompilerFacade {
    private Lexer lexer;
    private Parser parser;
    private CodeGenerator generator;
    
    public CompilerFacade() {
        this.lexer = new Lexer();
        this.parser = new Parser();
        this.generator = new CodeGenerator();
    }
    
    // 一键编译
    public String compile(String sourceCode) {
        String tokens = (1)______;
        String ast = (2)______;
        String code = (3)______;
        return (4)______;
    }
}

public class Client {
    public static void main(String[] args) {
        CompilerFacade compiler = new CompilerFacade();
        String result = compiler.compile("int main() { return 0; }");
        System.out.println("编译结果: " + result);
    }
}

答案

  • (1) lexer.tokenize(sourceCode)

  • (2) parser.parse(tokens)

  • (3) generator.generate(ast)

  • (4) code

阅卷要点

  • (1)(2)(3) 必须体现 Facade 对子系统方法的 顺序调用。顺序不能错(先词法、再语法、再生成),但方法名必须准确。

  • (4) 必须是 code(或 generator.generate(ast)),返回最终的编译结果。如果写 tokensast 会扣分,因为那不是最终产物。

  • 注意:Facade 内部的方法调用是通过 组合的成员变量lexerparsergenerator)调用,不是通过类名直接调用静态方法。


模拟题 3(下午代码填空 --- 外观类与单例结合)

某系统的外观类 ServiceFacade 需要设计为单例,封装 UserServiceOrderService 两个子系统。请补全(1)~(3)。

java 复制代码
class UserService {
    public String getUser(String id) { return "User:" + id; }
}

class OrderService {
    public String getOrder(String userId) { return "Order of " + userId; }
}

class ServiceFacade {
    private static final ServiceFacade (1)______ = new ServiceFacade();
    private UserService userService;
    private OrderService orderService;
    
    private ServiceFacade() {
        this.userService = new UserService();
        this.orderService = new OrderService();
    }
    
    public static ServiceFacade (2)______() {
        return (3)______;
    }
    
    public String getUserOrderInfo(String userId) {
        String user = userService.getUser(userId);
        String order = orderService.getOrder(userId);
        return user + " -> " + order;
    }
}

public class Client {
    public static void main(String[] args) {
        String info = ServiceFacade.getInstance().getUserOrderInfo("1001");
        System.out.println(info);
    }
}

答案

  • (1) INSTANCE

  • (2) getInstance

  • (3) INSTANCE

阅卷要点

  • (1) 必须是 INSTANCE(或 instance),这是单例的标准命名。static final 修饰表示饿汉式单例。

  • (2) 必须是 getInstance,这是单例的标准获取方法名。

  • (3) 必须是 INSTANCE,返回单例实例。不能写 new ServiceFacade()(构造器是 private)。

  • 此题结合了 单例模式外观模式,是软考下午题中常见的组合考法。


十、常见陷阱与注意事项

陷阱 1:误认为外观是创建型模式

外观属于 结构型 模式,因为它解决的是 类与类之间的结构关系 (Facade 与子系统的组合),而不是对象的创建问题。软考上午题如果问"以下属于创建型模式的是",选项里出现"外观" 不能选

陷阱 2:Facade 继承子系统类

这是软考 常见错误写法 。Facade 应该通过 组合 (持有子系统引用)来使用子系统,而不是继承子系统。如果 Facade 继承了子系统类,那就破坏了子系统的独立性,也违背了外观模式的初衷。软考代码填空里,Facade 与子系统之间是 关联/依赖关系(Facade 类里有子系统的成员变量),不是继承关系。

陷阱 3:认为外观阻止了直接访问子系统

外观模式 不阻止 客户端直接访问子系统。Facade 只是提供了一个 简化的入口 ,如果客户端需要更细粒度的控制,仍然可以直接调用子系统类。如果题干说"外观模式强制所有调用必须通过 Facade",那是 错误 的。

陷阱 4:与适配器模式混淆

表格

外观模式 适配器模式
封装 多个 子系统的复杂调用 转换 一个 类的接口
提供 新的高层 接口 已有接口 转为另一个接口
目的是 简化使用 目的是 兼容接口

如果类图里 Facade 连接多个子系统,且 Client 只连 Facade → 外观。如果 Adapter 连接 Target 和 Adaptee → 适配器。

陷阱 5:与代理模式混淆
外观模式 代理模式
封装 多个 子系统 控制 一个 对象的访问
Client 知道自己在调用 Facade Client 通常不知道自己在调用 Proxy
目的是 简化 目的是 控制
陷阱 6:与中介者模式混淆

这是软考 最难的辨析题

  • 外观 :Client → Facade → Subsystem(单向,Facade 封装子系统供客户端使用)。

  • 中介者 :Colleague ↔ Mediator ↔ Colleague(双向,Mediator 协调多个对等对象之间的交互)。

快速判断:如果类图里有一个中心类,多个子系统类只被中心类调用,且客户端只与中心类交互 → 外观。如果多个对等对象都通过中心类互相通信 → 中介者。

陷阱 7:Facade 的构造器参数

Facade 的构造器有两种设计方式:

  1. 内部创建 :在 Facade 构造器里 new Subsystem()(如场景二)。

  2. 外部注入:通过构造器参数传入子系统实例(如场景一)。

两种方式都算对,但软考代码填空时要注意:如果题干说 "Facade 自行管理子系统生命周期",则内部创建;如果题干说 "子系统由外部配置",则外部注入。


十一、总结

要点 内容
定义 为子系统中的一组接口提供一个统一的高层接口,使得子系统更加容易使用
分类 结构型模式(GoF 23 正式成员)
核心角色 Facade(外观)、Subsystem(子系统,多个)、Client(客户端)
核心思想 封装子系统的复杂调用逻辑,提供一个简洁的高层入口
设计原则 最少知识原则(迪米特法则):客户端只需与 Facade 交互
是否阻止直接访问 ❌ 不阻止。Facade 只是简化入口,客户端仍可直接访问子系统
与单例结合 外观类通常设计为单例(整个系统只需要一个门面)
与适配器区别 外观:简化多个子系统的使用;适配器:转换一个类的接口
与代理区别 外观:简化多个子系统;代理:控制一个对象的访问
与中介者区别 外观:单向封装子系统;中介者:双向协调对等对象
软考重点 代码填空(补全 Facade 对子系统的顺序调用);类图识别(Facade 连接多个 Subsystem);与中介者的辨析
答题技巧 看到 "封装复杂子系统"、"提供统一入口"、"简化调用" → 外观;看到 Facade 类封装多个子系统方法 → 确认外观

系列预告 :下一篇将讲 享元模式 ------ 当系统中存在大量相似对象、内存开销巨大时,如何通过共享技术有效地支持大量细粒度的对象。咱们下回见。

相关推荐
geovindu7 小时前
CSharp: Prototype Pattern
开发语言·后端·设计模式·.net·原型模式·创建型模式
ttod_qzstudio8 小时前
【软考设计模式】组合模式:“部分-整体“层次结构与树形对象统一操作精讲
设计模式·组合模式
ttod_qzstudio10 小时前
【软考设计模式】装饰模式:“套娃“式增强与动态职责扩展精讲
设计模式·装饰模式
烬羽11 小时前
MCP 多服务器架构实战:一个 Agent 同时操控地图、浏览器和文件
设计模式·设计
阿pin14 小时前
Android随笔-常用的设计模式
android·设计模式
儒雅的名14 小时前
GoF设计模式——策略模式
设计模式·bash·策略模式
折哥的程序人生 · 物流技术专研1 天前
第4篇:Lambda 简化策略模式(Java 8+)
java·设计模式·策略模式·函数式编程·lambda·代码简化·扩充系列
jsonbro1 天前
手把手带你实现发布订阅模式
前端·vue.js·设计模式
workflower1 天前
室内外配送机器人-应用路径
人工智能·机器学习·设计模式·矩阵·自动化