【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;
}
相关推荐
饼干哥哥4 小时前
我开发了一个「吃掉」别人Skill来升级的饕餮.Skill,现在免费开源
人工智能·设计模式·开源
CaffeinePro4 小时前
什么是系统架构?架构师到底在做什么?
设计模式·架构
AI人工智能+电脑小能手7 小时前
【大白话说Java面试题 第156题】【06_Spring篇】第16题:Spring 用到了哪些设计模式?
java·spring·设计模式·代理模式·工厂模式
前端百草阁8 小时前
JavaScript 设计模式(23 种)
开发语言·前端·javascript·设计模式
geovindu9 小时前
java: Singleton Pattern
java·开发语言·后端·单例模式·设计模式·创建型模式
geovindu1 天前
python: Functional Options Pattern
开发语言·后端·python·设计模式·惯用法模式·函数式选项模式
Kel1 天前
Pregel 为什么会成为LangGraph编排的心脏
人工智能·设计模式·架构
会周易的程序员1 天前
microLog 后端开发指南
开发语言·c++·物联网·设计模式·日志·iot·aiot
geovindu1 天前
go: Functional Options Pattern
开发语言·后端·设计模式·golang·函数式选项模式’·惯用法模式
Kel2 天前
MCP 传输链路全链路拆解:从字节流到协议栈的四层架构之旅
人工智能·设计模式·架构