【C++设计模式】单一职责原则

2023年8月26日,周六上午


目录


概述

单一职责原则(Single Responsibility Principle,SRP),它是面向对象设计中的一个基本原则。

单一职责原则的核心思想是,一个类应该只有一个引起它变化的原因。

换句话说,一个类应该只负责一项功能或职责

这样做的好处是,当需求发生变化时,只有与该功能相关的类需要进行修改,而不会影响其他不相关的功能。


一个简单的例子

cpp 复制代码
class FileManager {
public:
  void readFile(std::string filename) {
    // 读取文件的代码逻辑
  }

  void writeFile(std::string filename) {
    // 写入文件的代码逻辑
  }

  void deleteFile(std::string filename) {
    // 删除文件的代码逻辑
  }

  void encryptFile(std::string filename) {
    // 加密文件的代码逻辑
  }

  void compressFile(std::string filename) {
    // 压缩文件的代码逻辑
  }
};

在这个示例中,FileManager类负责文件的读取、写入、删除、加密和压缩等操作。

这个类违反了单一职责原则,因为它承担了多个不同的功能,即文件操作和文件处理。

为了遵循单一职责原则,我们可以将文件操作和文件处理分离为两个独立的类:

cpp 复制代码
class FileManager {
public:
  void readFile(std::string filename) {
    // 读取文件的代码逻辑
  }

  void writeFile(std::string filename) {
    // 写入文件的代码逻辑
  }

  void deleteFile(std::string filename) {
    // 删除文件的代码逻辑
  }
};


class FileProcessor {
public:
  void encryptFile(std::string filename) {
    // 加密文件的代码逻辑
  }

  void compressFile(std::string filename) {
    // 压缩文件的代码逻辑
  }
};

现在,FileManager类负责文件的基本操作,而FileProcessor类负责对文件进行加密和压缩等处理操作。这样,每个类都只有一个单一的职责,使得代码更加清晰、可维护和可扩展。

总结来说,单一职责原则要求将不同的职责分离到不同的类中,以确保每个类只负责一项功能。这样可以提高代码的可读性、可维护性和可扩展性,减少代码之间的耦合。


用单一职责原则来设计一个简单的学生管理系统

使用单一职责原则来设计一个简单的学生管理系统,可以将功能分解为以下几个类:

  1. Student类:表示学生对象,包含学生的基本信息(如姓名、学号、年龄)以及相关操作(如获取学生信息、修改学生信息)。
  2. StudentDatabase类:负责学生信息的存储和管理,包含增加学生、删除学生、查找学生等操作。
  3. StudentUI类:负责与用户交互,显示菜单选项,接收用户输入,并调用StudentDatabase类中的方法来执行相应的操作。
cpp 复制代码
#include <iostream>
#include <vector>
#include <string>

class Student {
private:
  std::string name;
  int studentId;
  int age;

public:
  Student(std::string name, int studentId, int age)
    : name(name), studentId(studentId), age(age) {}

  std::string getName() const {
    return name;
  }

  int getStudentId() const {
    return studentId;
  }

  int getAge() const {
    return age;
  }

  void updateName(std::string newName) {
    name = newName;
  }

  void updateAge(int newAge) {
    age = newAge;
  }
};

class StudentDatabase {
private:
  std::vector<Student> students;

public:
  void addStudent(const Student& student) {
    students.push_back(student);
  }

  void removeStudent(int studentId) {
    for (auto it = students.begin(); it != students.end(); ++it) {
      if (it->getStudentId() == studentId) {
        students.erase(it);
        break;
      }
    }
  }

  Student findStudent(int studentId) const {
    for (const auto& student : students) {
      if (student.getStudentId() == studentId) {
        return student;
      }
    }
    // 如果找不到对应的学生,则返回一个空的Student对象
    return Student("", -1, -1);
  }

  std::vector<Student> getAllStudents() const {
    return students;
  }
};

class StudentUI {
private:
  StudentDatabase studentDB;

public:
  void displayMenu() {
    std::cout << "=== 学生管理系统 ===" << std::endl;
    std::cout << "1. 添加学生" << std::endl;
    std::cout << "2. 删除学生" << std::endl;
    std::cout << "3. 查找学生" << std::endl;
    std::cout << "4. 显示所有学生" << std::endl;
    std::cout << "0. 退出" << std::endl;
  }

  void addStudent() {
    std::string name;
    int studentId, age;

    std::cout << "请输入学生姓名: ";
    std::cin >> name;
    std::cout << "请输入学生学号: ";
    std::cin >> studentId;
    std::cout << "请输入学生年龄: ";
    std::cin >> age;

    Student student(name, studentId, age);
    studentDB.addStudent(student);
    std::cout << "成功添加学生!" << std::endl;
  }

  void removeStudent() {
    int studentId;

    std::cout << "请输入要删除的学生学号: ";
    std::cin >> studentId;

    studentDB.removeStudent(studentId);
    std::cout << "成功删除学生!" << std::endl;
  }

  void findStudent() {
    int studentId;

    std::cout << "请输入要查找的学生学号: ";
    std::cin >> studentId;

    Student student = studentDB.findStudent(studentId);
    if (student.getStudentId() != -1) {
      std::cout << "找到学生: " << student.getName() << std::endl;
      std::cout << "学号: " << student.getStudentId() << std::endl;
      std::cout << "年龄: " << student.getAge() << std::endl;
    } else {
      std::cout << "未找到该学生!" << std::endl;
    }
  }

  void displayAllStudents() {
    std::vector<Student> students = studentDB.getAllStudents();
    if (students.empty()) {
      std::cout << "暂无学生信息!" << std::endl;
    } else {
      std::cout << "所有学生信息:" << std::endl;
      for (const auto& student : students) {
        std::cout << "姓名: " << student.getName() << ", ";
        std::cout << "学号: " << student.getStudentId() << ", ";
        std::cout << "年龄: " << student.getAge() << std::endl;
      }
    }
  }

  void run() {
    int choice;

    do {
      displayMenu();
      std::cout << "请输入选项: ";
      std::cin >> choice;

      switch (choice) {
        case 1:
          addStudent();
          break;
        case 2:
          removeStudent();
          break;
        case 3:
          findStudent();
          break;
        case 4:
          displayAllStudents();
          break;
        case 0:
          std::cout << "退出程序!" << std::endl;
          break;
        default:
          std::cout << "无效的选项,请重新输入!" << std::endl;
      }
    } while (choice != 0);
  }
};

int main() {
  StudentUI studentUI;
  studentUI.run();

  return 0;
}
相关推荐
前端大白话16 分钟前
Vue2和Vue3语法糖差异大揭秘:一文读懂,开发不纠结!
javascript·vue.js·设计模式
前端大白话22 分钟前
JavaScript中`Symbol.for()`和`Symbol()`的区别,在创建全局唯一的`Symbol`值时如何选择使用?
前端·javascript·设计模式
CHQIUU1 小时前
Java 设计模式心法之第25篇 - 中介者 (Mediator) - 用“中央协调”降低对象间耦合度
java·设计模式·中介者模式
Pasregret2 小时前
备忘录模式:实现对象状态撤销与恢复的设计模式
运维·服务器·设计模式
碎梦归途4 小时前
23种设计模式-行为型模式之备忘录模式(Java版本)
java·jvm·设计模式·软考·备忘录模式·软件设计师·行为型模式
东阳马生架构12 小时前
Sentinel源码—8.限流算法和设计模式总结二
算法·设计模式·sentinel
冰茶_13 小时前
C#中常见的设计模式
java·开发语言·microsoft·设计模式·微软·c#·命令模式
Niuguangshuo14 小时前
Python 设计模式:访问者模式
python·设计模式·访问者模式
不当菜虚困14 小时前
JAVA设计模式——(七)代理模式
java·设计模式·代理模式
RationalDysaniaer16 小时前
Go设计模式-观察者模式
观察者模式·设计模式·golang