通过C++程序示例理解设计模式中的外观模式

一、设计模式中的外观模式

  • 定义: 外观模式(Facade Pattern)提供了一个统一的接口,用来访问子系统中的一群接口。其目的是简化子系统的使用,消除客户端和子系统之间的耦合,让子系统内部的模块更容易维护和扩展。
  • 要点: 
    • 外观模式不暴露子系统的内部细节,仅暴露一个应用程序所需进行的操作。
    • 外观类是客户端与子系统之前的第一层封装,对于多个子系统,客户端可以通过外观类的公共接口依次访问它们。
    • 外观模式旨在降低系统的复杂度,其最大的优点就是能够让客户端和子系统之间的耦合度降到最低。

二、C++程序示例说明

1. 示例一

我们来看一个简单的外观模式示例,假设我们有一个计算器程序,里面有加减乘除四个功能,每个功能都需要调用一堆子系统类的方法才能完成,代码如下:

#include <iostream>

class Adder {
public:
    int add(int a, int b) {
        return a + b;
    }
};

class Subtractor {
public:
    int subtract(int a, int b) {
        return a - b;
    }
};

class Multiplier {
public:
    int multiply(int a, int b) {
        return a * b;
    }
};

class Divider {
public:
    int divide(int a, int b) {
        if (b == 0) {
            throw std::exception("Divided by zero!");
        }
        return a / b;
    }
};

class Calculator {
public:
    Calculator() : adder_(), subtractor_(), multiplier_(), divider_() {}

    int add(int a, int b) {
        return adder_.add(a, b);
    }

    int subtract(int a, int b) {
        return subtractor_.subtract(a, b);
    }

    int multiply(int a, int b) {
        return multiplier_.multiply(a, b);
    }

    int divide(int a, int b) {
        return divider_.divide(a, b);
    }

private:
    Adder adder_;
    Subtractor subtractor_;
    Multiplier multiplier_;
    Divider divider_;
};

int main() {
    Calculator calculator;
    std::cout << calculator.add(1, 2) << std::endl;
    std::cout << calculator.subtract(1, 2) << std::endl;
    std::cout << calculator.multiply(1, 2) << std::endl;
    std::cout << calculator.divide(1, 2) << std::endl;
    return 0;
}

上面这段代码中,四个计算功能分别实现在Adder、Subtractor、Multiplier和Divider类中,而这四个类又组成了Calculator类,作为一个子系统。客户端必须要知道这些类的存在,并且才能使用它们提供的计算功能。这对于客户端来说会很麻烦,因为客户端需要知道子系统内部的实现。

所以,我们可以引入外观模式来简化客户端和子系统之间的交互。我们添加一个新的类CalculatorFacade,把四个计算功能封装成了一个接口,客户端只需要调用这一个接口就可以完成各种计算,如下所示:

#include <iostream>

class Adder {
public:
    int add(int a, int b) {
        return a + b;
    }
};

class Subtractor {
public:
    int subtract(int a, int b) {
        return a - b;
    }
};

class Multiplier {
public:
    int multiply(int a, int b) {
        return a * b;
    }
};

class Divider {
public:
    int divide(int a, int b) {
        if (b == 0) {
            throw std::exception("Divided by zero!");
        }
        return a / b;
    }
};

class CalculatorFacade {
public:
    CalculatorFacade() : adder_(), subtractor_(), multiplier_(), divider_() {}

    int add(int a, int b) {
        return adder_.add(a, b);
    }

    int subtract(int a, int b) {
        return subtractor_.subtract(a, b);
    }

    int multiply(int a, int b) {
        return multiplier_.multiply(a, b);
    }

    int divide(int a, int b) {
        return divider_.divide(a, b);
    }

private:
    Adder adder_;
    Subtractor subtractor_;
    Multiplier multiplier_;
    Divider divider_;
};

int main() {
    CalculatorFacade calc;
    std::cout << calc.add(1, 2) << std::endl;
    std::cout << calc.subtract(1, 2) << std::endl;
    std::cout << calc.multiply(1, 2) << std::endl;
    std::cout << calc.divide(1, 2) << std::endl;
    return 0;
}

这里引入了CalculatorFacade类,作为客户端和子系统之间的交互层,把四个计算功能封装成了一个接口,客户端只需要和这一个类打交道就可以了,这样客户端和子系统之间的耦合度就降低了。

2. 示例二

再看一下一个更复杂的例子,假设我们有一个情景处理系统,要求实现一个包含多个子系统的日程管理系统。日程管理系统功能复杂,包含了提醒、加密、存储等多个模块,下面我们来看看如何使用外观模式简化这个系统。

首先我们定义了三个子系统类Reminder、Encrypter和Storage,代码如下:

#include <iostream>
#include <string>

class Reminder {
public:
    void remind(const std::string& action) {
        std::cout << "Reminder: " << action << std::endl;
    }
};

class Encrypter {
public:
    std::string encrypt(const std::string& data) {
        std::string result = data;
        std::cout << "Encrypter: " << result << std::endl;
        return result;
    }
};

class Storage {
public:
    void store(const std::string& data) {
        std::cout << "Storage: " << data << std::endl;
    }
};

这三个类分别实现了提醒、加密和存储功能。然后我们定义了一个类ScheduleManagerFacade,由于项目中要经常访问这三个子系统,所以这个类就成为了他们的管理者,代码如下:

#include <iostream>
#include <string>

class Reminder {
public:
    void remind(const std::string& action) {
        std::cout << "Reminder: " << action << std::endl;
    }
};

class Encrypter {
public:
    std::string encrypt(const std::string& data) {
        std::string result = data;
        std::cout << "Encrypter: " << result << std::endl;
        return result;
    }
};

class Storage {
public:
    void store(const std::string& data) {
        std::cout << "Storage: " << data << std::endl;
    }
};

class ScheduleManagerFacade {
public:
    ScheduleManagerFacade() : reminder_(), encrypter_(), storage_() {}

    void createSchedule(const std::string& data) {
        reminder_.remind("Create schedule.");
        std::string encrypted_data = encrypter_.encrypt(data);
        storage_.store(encrypted_data);
    }

    void updateSchedule(const std::string& data) {
        reminder_.remind("Update schedule.");
        std::string encrypted_data = encrypter_.encrypt(data);
        storage_.store(encrypted_data);
    }

    void deleteSchedule(const std::string& data) {
        reminder_.remind("Delete schedule.");
        std::string encrypted_data = encrypter_.encrypt(data);
        storage_.store(encrypted_data);
    }

    void viewSchedule(const std::string& data) {
        reminder_.remind("View schedule.");
        std::string encrypted_data = encrypter_.encrypt(data);
        storage_.store(encrypted_data);
    }

private:
    Reminder reminder_;
    Encrypter encrypter_;
    Storage storage_;
};

int main() {
    ScheduleManagerFacade scheduleManagerFacade;
    scheduleManagerFacade.createSchedule("This is a new schedule.");
    scheduleManagerFacade.updateSchedule("This schedule has been updated.");
    scheduleManagerFacade.deleteSchedule("This schedule has been deleted.");
    scheduleManagerFacade.viewSchedule("This schedule is view only.");
    return 0;
}

上面这段代码中,我们首先定义了Reminder、Encrypter和Storage三个子系统类,然后定义了一个ScheduleManagerFacade类作为外观类,客户端只需要和这个类打交道就可以了。ScheduleManagerFacade的每个成员函数都封装了子系统的实现细节,对外提供了统一的接口,可以方便地对日程进行创建、更新、删除和查看操作,不必去理解复杂的子系统实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:通过C++程序示例理解设计模式中的外观模式 - Python技术站

(0)
上一篇 2023年5月30日
下一篇 2023年5月30日

相关文章

  • 天谕雷罡圣堂怎么加点 天谕雷罡圣堂加点攻略

    天谕雷罡圣堂加点攻略 天谕雷罡圣堂是一款策略RPG游戏,在游戏中加点是非常重要的一件事情。本文将为大家介绍如何正确地加点以及天谕雷罡圣堂加点攻略。 加点原则 根据职业特长加点,如攻击型职业加攻击,防御型职业加防御等; 根据职业技能加点,如有狂暴技能的职业需要加点提升狂暴效果等; 根据自己的游戏风格加点,如喜欢输出的可以加攻击,喜欢坦克的可以加防御等; 根据B…

    C 2023年5月22日
    00
  • 用C语言实现计算器功能

    关于用C语言实现计算器功能的攻略,可以分为以下几个步骤: 1. 设计计算器的UI界面 计算器的UI界面主要是指输入框、计算器按钮、结果框等。需要先设计好UI界面,确定每个按钮的功能以及对应输入和输出的数据类型。可以使用C语言的图形库或者基于控制台实现。 下面是一个使用控制台实现的简单计算器UI界面的示例图: ————————-…

    C 2023年5月23日
    00
  • Audition打开提示错误代码0xc000007b怎么办?

    问题描述: Audition 是Adobe公司出品的专业音频编辑软件,但是有时候各位用户打开Audition时会遇到提示错误代码 0xc000007b 的提示,导致无法正常运行。这个错误通常是由于缺失或损坏系统组件或本地库文件而引起的。下面我们来了解一下如何解决Audition打开提示错误代码0xc000007b的问题。 解决方案: 以下是针对Auditio…

    C 2023年5月23日
    00
  • 用C语言实现猜数字游戏

    用C语言实现猜数字游戏完整攻略 1. 游戏规则 本猜数字游戏的规则非常简单,系统在1到100之间随机生成一个数字,然后玩家通过输入进行猜测,如果猜中则游戏胜利,若猜测的数字小于或大于目标数字,则系统会提示玩家重新猜测。 2. 程序实现 (1)首先我们需要定义一个目标数字,该数字需要随机生成。使用rand()函数可以生成一个随机数,我们通过加上1的操作让生成的…

    C 2023年5月23日
    00
  • GCC 编译c程序的方法及过程解析

    GCC 编译 C 程序的方法及过程解析 什么是 GCC GCC(GNU Compiler Collection)是一个开源的编译器集合,它能够将 C、C++、Objective-C、Fortran、Ada、Go 等语言编写的代码翻译成计算机能够理解的机器码。GCC 能够在多种平台和操作系统中运行,比如 Linux、Unix、Windows、macOS 等。 …

    C 2023年5月23日
    00
  • C++使用map实现多进程拷贝文件的程序思路

    为了实现使用map实现多进程拷贝文件的程序,我们可以按照以下步骤操作: 步骤一:导入必要的头文件 在写C++多进程拷贝文件程序时,需要用到以下两个头文件: #include <unistd.h> // 提供fork()函数 #include <sys/wait.h> // 提供wait()函数 步骤二:打开需要读取和写入的文件 使用C…

    C 2023年5月30日
    00
  • C++类和对象到底是什么

    C++是一种面向对象的程序设计语言,类和对象是它最为重要的特性之一。 类是对现实事物的抽象,是对具有相同属性和行为的对象的实现。例如,对于一个图书类,每本书都会有书名、作者、出版社、价格等属性,每本书都可以借阅、购买、查阅等行为。在C++中,类的定义以class关键字开始,紧跟着是类的名称和花括号内的成员变量和成员函数。 class Book{ public…

    C 2023年5月23日
    00
  • c语言同名标靶点自动匹配算法实现实例代码

    c语言同名标靶点自动匹配算法实现实例代码攻略 简介 本文介绍如何实现一种基于c语言的同名标靶点自动匹配算法。该算法可以用于自动匹配两个c语言源代码文件中同名的函数或变量,从而提高代码的可读性和可维护性。 实现思路 实现该算法的主要思路如下: 对两个c语言源代码文件进行词法分析,将每个单词转换为token。 根据token序列获取每个函数或变量的名称和类型,并…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部