结构型模式:⑤外观模式(Facade Pattern)

结构型模式:⑤外观模式(Facade Pattern)

核心思想

为复杂子系统提供一个统一的高层接口,隐藏子系统内部的复杂逻辑、依赖关系和调用顺序,使客户端只需调用该接口即可完成复杂操作,无需关心子系统内部的细节。

核心本质

封装复杂性 + 统一入口,通过 “外观类(或结构体)” 协调子系统中多个组件的交互,降低客户端与子系统的耦合度,同时遵循 “最少知识原则”(客户端只需与外观交互,无需了解子系统内部组件)。

典型场景

比如 “家庭影院”:子系统包含投影仪、音响、播放器、灯光等组件,播放电影需要按 “关闭灯光→打开投影仪→打开音响→启动播放器” 的顺序操作;关闭时则相反。外观模式会封装一个 “家庭影院控制器”(外观),客户端只需调用 “播放电影”“关闭影院” 两个接口,无需手动操作每个组件。

C语言编写

场景示例

子系统:投影仪(Projector)、音响(Audio)、播放器(Player)、灯光(Light);外观:家庭影院控制器(HomeTheaterFacade);客户端通过外观的 watch_movie/end_movie 接口,一键完成播放 / 关闭操作。

关键要点

1.子系统独立性:子系统组件(投影仪、音响等)是独立的,拥有自己的接口,可单独使用(如单独打开投影仪),不依赖外观。
2.外观组合子系统:外观结构体通过成员指针持有所有子系统组件的引用,是协调子系统的核心。
3.统一高层接口:外观提供 watch_movie/end_movie 两个简单接口,内部封装了子系统的复杂调用顺序(如播放电影需 6 步操作),客户端无需关心细节。
4.协调逻辑封装:外观负责子系统的调用顺序和依赖关系(如先关灯光再开投影仪),修改逻辑时只需改外观,无需改客户端。
5.解耦客户端与子系统:客户端仅依赖外观接口,不直接操作子系统组件,降低了耦合度(如更换音响品牌,只需修改外观中音响的创建逻辑,客户端无感知)。
6.内存管理:外观的 destroy 方法统一释放所有子系统组件,避免客户端手动管理多个子系统的内存。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// -------------------------- 1. 子系统组件(Subsystem):独立功能模块 --------------------------
// 子系统1:投影仪
typedef struct Projector {
    void (*turn_on)(struct Projector* self);
    void (*turn_off)(struct Projector* self);
    char name[32];
} Projector;

void projector_turn_on(Projector* self) {
    printf("[%s] 启动,切换到电影模式\n", self->name);
}

void projector_turn_off(Projector* self) {
    printf("[%s] 关闭\n", self->name);
}

Projector* create_projector(const char* name) {
    Projector* p = (Projector*)malloc(sizeof(Projector));
    strncpy(p->name, name, sizeof(p->name));
    p->turn_on = projector_turn_on;
    p->turn_off = projector_turn_off;
    return p;
}

// 子系统2:音响
typedef struct Audio {
    void (*turn_on)(struct Audio* self);
    void (*turn_off)(struct Audio* self);
    void (*adjust_volume)(struct Audio* self, int volume);
    char name[32];
} Audio;

void audio_turn_on(Audio* self) {
    printf("[%s] 启动\n", self->name);
}

void audio_turn_off(Audio* self) {
    printf("[%s] 关闭\n", self->name);
}

void audio_adjust_volume(Audio* self, int volume) {
    printf("[%s] 音量调整到:%d\n", self->name, volume);
}

Audio* create_audio(const char* name) {
    Audio* a = (Audio*)malloc(sizeof(Audio));
    strncpy(a->name, name, sizeof(a->name));
    a->turn_on = audio_turn_on;
    a->turn_off = audio_turn_off;
    a->adjust_volume = audio_adjust_volume;
    return a;
}

// 子系统3:播放器
typedef struct Player {
    void (*turn_on)(struct Player* self);
    void (*turn_off)(struct Player* self);
    void (*play)(struct Player* self, const char* movie);
    char name[32];
} Player;

void player_turn_on(Player* self) {
    printf("[%s] 启动\n", self->name);
}

void player_turn_off(Player* self) {
    printf("[%s] 关闭\n", self->name);
}

void player_play(Player* self, const char* movie) {
    printf("[%s] 播放电影:《%s》\n", self->name, movie);
}

Player* create_player(const char* name) {
    Player* p = (Player*)malloc(sizeof(Player));
    strncpy(p->name, name, sizeof(p->name));
    p->turn_on = player_turn_on;
    p->turn_off = player_turn_off;
    p->play = player_play;
    return p;
}

// 子系统4:灯光
typedef struct Light {
    void (*turn_on)(struct Light* self);
    void (*turn_off)(struct Light* self);
    char name[32];
} Light;

void light_turn_on(Light* self) {
    printf("[%s] 打开\n", self->name);
}

void light_turn_off(Light* self) {
    printf("[%s] 关闭(营造观影氛围)\n", self->name);
}

Light* create_light(const char* name) {
    Light* l = (Light*)malloc(sizeof(Light));
    strncpy(l->name, name, sizeof(l->name));
    l->turn_on = light_turn_on;
    l->turn_off = light_turn_off;
    return l;
}

// -------------------------- 2. 外观(Facade):家庭影院控制器 --------------------------
typedef struct HomeTheaterFacade {
    // 组合子系统组件(核心:外观持有子系统引用)
    Projector* projector;
    Audio* audio;
    Player* player;
    Light* light;

    // 统一接口:客户端调用的高层方法
    void (*watch_movie)(struct HomeTheaterFacade* self, const char* movie);
    void (*end_movie)(struct HomeTheaterFacade* self);
    void (*destroy)(struct HomeTheaterFacade* self);
} HomeTheaterFacade;

// 外观方法1:播放电影(协调子系统调用顺序)
void home_theater_watch_movie(HomeTheaterFacade* self, const char* movie) {
    printf("\n=== 准备播放电影 ===");
    self->light->turn_off(self->light);       // 1. 关闭灯光
    self->projector->turn_on(self->projector); // 2. 打开投影仪
    self->audio->turn_on(self->audio);         // 3. 打开音响
    self->audio->adjust_volume(self->audio, 80); // 4. 调整音量
    self->player->turn_on(self->player);       // 5. 打开播放器
    self->player->play(self->player, movie);   // 6. 播放电影
    printf("=== 电影播放中 ===\n");
}

// 外观方法2:结束电影(反向协调子系统关闭顺序)
void home_theater_end_movie(HomeTheaterFacade* self) {
    printf("\n=== 准备关闭影院 ===");
    self->player->turn_off(self->player);      // 1. 关闭播放器
    self->audio->turn_off(self->audio);        // 2. 关闭音响
    self->projector->turn_off(self->projector); // 3. 关闭投影仪
    self->light->turn_on(self->light);         // 4. 打开灯光
    printf("=== 影院已关闭 ===\n");
}

// 外观销毁:释放所有子系统组件
void home_theater_destroy(HomeTheaterFacade* self) {
    if (self != NULL) {
        free(self->projector);
        free(self->audio);
        free(self->player);
        free(self->light);
        free(self);
    }
}

// 创建外观实例(初始化子系统组件)
HomeTheaterFacade* create_home_theater_facade() {
    HomeTheaterFacade* facade = (HomeTheaterFacade*)malloc(sizeof(HomeTheaterFacade));
    // 初始化子系统组件
    facade->projector = create_projector("索尼投影仪");
    facade->audio = create_audio("BOSE音响");
    facade->player = create_player("蓝光播放器");
    facade->light = create_light("客厅灯光");
    // 绑定外观接口
    facade->watch_movie = home_theater_watch_movie;
    facade->end_movie = home_theater_end_movie;
    facade->destroy = home_theater_destroy;
    return facade;
}

// -------------------------- 测试代码(客户端) --------------------------
int main() {
    // 1. 创建外观实例(客户端仅与外观交互)
    HomeTheaterFacade* theater = create_home_theater_facade();

    // 2. 客户端一键播放电影(无需关心子系统细节)
    theater->watch_movie(theater, "星际穿越");

    // 3. 客户端一键关闭影院
    theater->end_movie(theater);

    // 4. 释放资源
    theater->destroy(theater);

    return 0;
}

C++语言实现

同 C 语言:子系统(Projector/Audio/Player/Light)+ 外观(HomeTheaterFacade),客户端一键操作家庭影院。通过 “独立类实现子系统组件”“外观类组合子系统实例”,利用类的封装性隐藏子系统细节,提供简洁的高层接口,且通过智能指针自动管理内存。

关键要点

1.子系统封装:子系统组件(Projector/Audio 等)是独立类,封装自身功能,对外提供清晰接口,不依赖外观。
2.外观组合子系统:外观类通过 std::unique_ptr 持有子系统实例,智能指针自动管理内存,无需手动释放。
3.高层接口简洁:外观提供 WatchMovie/EndMovie 两个核心接口,客户端调用时无需知道内部调用顺序(如先关灯光还是先开投影仪)。
4.逻辑集中管理:子系统的调用顺序、依赖关系集中在外观中,修改时只需调整外观代码(如新增 “打开幕布” 组件,只需在外观中添加调用),符合 “开闭原则”。
5.低耦合:客户端仅依赖 HomeTheaterFacade 类,与子系统组件完全解耦(如更换投影仪品牌,只需修改外观中 Projector 的创建逻辑,客户端无感知)。
6.类型安全:C++ 的类和成员函数提供编译期类型检查,避免 C 语言中函数指针绑定错误或类型转换风险。

#include <iostream>
#include <string>
#include <memory> // 智能指针(自动管理内存)

// -------------------------- 1. 子系统组件(Subsystem):独立类 --------------------------
// 子系统1:投影仪
class Projector {
public:
    explicit Projector(std::string name) : name_(std::move(name)) {}

    void TurnOn() const {
        std::cout << "[" << name_ << "] 启动,切换到电影模式" << std::endl;
    }

    void TurnOff() const {
        std::cout << "[" << name_ << "] 关闭" << std::endl;
    }

private:
    std::string name_;
};

// 子系统2:音响
class Audio {
public:
    explicit Audio(std::string name) : name_(std::move(name)) {}

    void TurnOn() const {
        std::cout << "[" << name_ << "] 启动" << std::endl;
    }

    void TurnOff() const {
        std::cout << "[" << name_ << "] 关闭" << std::endl;
    }

    void AdjustVolume(int volume) const {
        std::cout << "[" << name_ << "] 音量调整到:" << volume << std::endl;
    }

private:
    std::string name_;
};

// 子系统3:播放器
class Player {
public:
    explicit Player(std::string name) : name_(std::move(name)) {}

    void TurnOn() const {
        std::cout << "[" << name_ << "] 启动" << std::endl;
    }

    void TurnOff() const {
        std::cout << "[" << name_ << "] 关闭" << std::endl;
    }

    void Play(const std::string& movie) const {
        std::cout << "[" << name_ << "] 播放电影:《" << movie << "》" << std::endl;
    }

private:
    std::string name_;
};

// 子系统4:灯光
class Light {
public:
    explicit Light(std::string name) : name_(std::move(name)) {}

    void TurnOn() const {
        std::cout << "[" << name_ << "] 打开" << std::endl;
    }

    void TurnOff() const {
        std::cout << "[" << name_ << "] 关闭(营造观影氛围)" << std::endl;
    }

private:
    std::string name_;
};

// -------------------------- 2. 外观(Facade):家庭影院控制器 --------------------------
class HomeTheaterFacade {
public:
    // 构造函数:初始化子系统组件(智能指针自动管理内存)
    HomeTheaterFacade() 
        : projector_(std::make_unique<Projector>("索尼投影仪")),
          audio_(std::make_unique<Audio>("BOSE音响")),
          player_(std::make_unique<Player>("蓝光播放器")),
          light_(std::make_unique<Light>("客厅灯光")) {}

    // 统一高层接口:播放电影
    void WatchMovie(const std::string& movie) const {
        std::cout << "\n=== 准备播放电影 ===" << std::endl;
        light_->TurnOff();         // 1. 关闭灯光
        projector_->TurnOn();      // 2. 打开投影仪
        audio_->TurnOn();          // 3. 打开音响
        audio_->AdjustVolume(80);  // 4. 调整音量
        player_->TurnOn();         // 5. 打开播放器
        player_->Play(movie);      // 6. 播放电影
        std::cout << "=== 电影播放中 ===\n" << std::endl;
    }

    // 统一高层接口:结束电影
    void EndMovie() const {
        std::cout << "=== 准备关闭影院 ===" << std::endl;
        player_->TurnOff();        // 1. 关闭播放器
        audio_->TurnOff();         // 2. 关闭音响
        projector_->TurnOff();     // 3. 关闭投影仪
        light_->TurnOn();          // 4. 打开灯光
        std::cout << "=== 影院已关闭 ===\n" << std::endl;
    }

private:
    // 组合子系统组件(智能指针自动释放内存)
    std::unique_ptr<Projector> projector_;
    std::unique_ptr<Audio> audio_;
    std::unique_ptr<Player> player_;
    std::unique_ptr<Light> light_;
};

// -------------------------- 测试代码(客户端) --------------------------
int main() {
    // 1. 创建外观实例(客户端仅与外观交互)
    HomeTheaterFacade theater;

    // 2. 客户端一键播放电影(无需关心子系统细节)
    theater.WatchMovie("星际穿越");

    // 3. 客户端一键关闭影院
    theater.EndMovie();

    return 0; // 智能指针自动销毁所有子系统组件,无需手动释放
}

外观模式核心总结(C vs C++)

在这里插入图片描述

设计原则

1.最少知识原则:客户端只需了解外观,无需了解子系统内部组件;
2.单一职责原则:外观负责协调子系统,子系统负责自身功能,职责清晰;
3.开闭原则:扩展子系统时(如新增组件),只需修改外观,无需修改客户端和现有子系统。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值