前言
提示:这里可以添加本文要记录的大概内容:
例如:软件设计的七大架构设计,指导着软件设计的。
提示:以下是本篇文章正文内容,下面案例可供参考
一、开闭原则
1.开闭原则的定义
开闭原则(Open-Closed Principle, OCP)指一个软件实体如类,模块和函数应对扩展开放,对修改封闭,即该原则是对软件扩展和修改的一项原则,强调的是用抽象构建框架,用实现扩展细节,目的是提高软件的可复用性和可维护性。该原则可以建立稳定灵活的系统,如:版本更新,我们尽可能不修改源码,但是可以增加新功能。
- 实现开闭原则的核心思想就是面向抽象的编程。
2. 使用开闭原则解决实际问题
- 如设计一个学生管理系统,该学生管理系统包括对学生信息的存储,包括学生的年龄,性别,学历等。案例代码如下
class CStudentOptImp { public: virtual std::string GetName() = 0; virtual int GetAge() = 0; virtual std::string GetEducation() = 0; }; class CStudent: public CStudentOptImp { public: CStudent(const std::string name, const int age, const std::string education) :m_sName(name), m_iAge(age), m_sEducation(education) { } virtual std::string GetName() { return m_sName; } virtual int GetAge() { return m_iAge; } virtual std::string GetEducation() { return m_sEducation; } private: std::string m_sName; int m_iAge; std::string m_sEducation; }; class CStudentRecord :public CStudent { public: CStudentRecord(const std::string name, const int age, const std::string education, const int record) :CStudent(name, age, education), m_iRecord(record) { } int GetRecord() { return m_iRecord; } private: int m_iRecord; }; void test01() { std::shared_ptr<CStudent> p = std::shared_ptr<CStudent>(new CStudent("venus", 26, "硕士")); std::cout << "姓名:" << p->GetName() << "\t年龄:" << p->GetAge() << "\t学历:" << p->GetEducation() << std::endl; } int main() { test01(); return 0; }
案例结果如下:
而如果此时增加了学生的成绩信息,就需要修改Student类,这项操作是很不稳定的,因为系统中别的类可能调用了该类,修改可能会导致别的功能出现错误或者bug,因而软件开发过程中需要遵循开闭原则,只能通过添加代码达到目的,而不能通过修改代码。如下,此时可以通过继承,增加代码达到目的。详细代码如下:
class CStudentOptImp { public: virtual std::string GetName() = 0; virtual int GetAge() = 0; virtual std::string GetEducation() = 0; }; class CStudent: public CStudentOptImp { public: CStudent(const std::string name, const int age, const std::string education) :m_sName(name), m_iAge(age), m_sEducation(education) { } virtual std::string GetName() { return m_sName; } virtual int GetAge() { return m_iAge; } virtual std::string GetEducation() { return m_sEducation; } private: std::string m_sName; int m_iAge; std::string m_sEducation; }; class CStudentRecord :public CStudent { public: CStudentRecord(const std::string name, const int age, const std::string education, const int record) :CStudent(name, age, education), m_iRecord(record) { } int GetRecord() { return m_iRecord; } private: int m_iRecord; }; void test01() { std::shared_ptr<CStudent> p = std::shared_ptr<CStudent>(new CStudent("venus", 26, "硕士")); std::cout << "姓名:" << p->GetName() << "\t年龄:" << p->GetAge() << "\t学历:" << p->GetEducation() << std::endl; } void test02() { std::shared_ptr<CStudentRecord> p = std::shared_ptr<CStudentRecord>(new CStudentRecord("venus", 26, "硕士", 100)); std::cout << "姓名:" << p->GetName() << "\t年龄:" << p->GetAge() << "\t学历:" << p->GetEducation() << "\t成绩:" << p->GetRecord() << std::endl; } int main() { //test01(); test02(); return 0; }
- 案例结果如下:
- 最后回顾以下整个开闭原则的类图关系:
二、依赖倒置原则
1.依赖倒置原则的定义
- 依赖倒置原则(Dependence Inversion Principle,DIP)指设计代码结构时,高层模块不应该依赖底层模块。二者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象。 通过依赖倒置可以减低类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性。
2.使用依赖倒置原则解决实际问题
- 我们以张三丰为例,建立张三丰类如下。
#include <iostream> class Zhangshanfen { public: void StudyTaiChiSword() { std::cout << "学习了太极剑" << std::endl; } void StudyTaiJiBoxing() { std::cout << "学习了太极拳" << std::endl; } }; int test01() { std::shared_ptr<Zhangshanfen> p = std::shared_ptr<Zhangshanfen>(new Zhangshanfen); p->StudyTaiChiSword(); p->StudyTaiJiBoxing(); return 0; } int main() { test01(); return 0; }
- 上面代码效果:
- 上面代码,如果当张三丰想学习武当剑法的时候,需要重写该段代码,这样程序就会变得不稳定。因此可以考虑将各种武功抽象出来,形成一个抽象类。代码如下:
#include <iostream> class Kungfu { public: virtual void Study() = 0; }; class TaiJiSword: public Kungfu { public: virtual void Study() override { std::cout << "学习太极剑" << std::endl; } }; class TaiJiBoxing :public Kungfu { public: virtual void Study() override { std::cout << "学习太极拳" << std::endl; } }; class WudangSwordTechnique :public Kungfu { public: virtual void Study() override { std::cout << "学习武当剑法" << std::endl; } }; class Zhangshanfen { public: void Study(Kungfu* kungfu) { kungfu->Study(); } }; int test01() { Zhangshanfen* p = new Zhangshanfen(); p->Study(new TaiJiSword); p->Study(new TaiJiBoxing); p->Study(new WudangSwordTechnique); return 0; } int main() { test01(); return 0; }
该代码的演示效果如下:
- 这个时候不管张三丰想学什么新的武功,对于新的武功,只需要新建一个类,通过传参的方式告诉张三丰,而不需要修改底层代码。实际上,这是一种大家非常熟悉的方式, 叫做依赖注入。此外注入的方式还有构造器注入方式和Setter注入方式,下面来看构造器注入方式。
class Zhangshanfen { public: Zhangshanfen(Kungfu* kunfu) { this->kunfu = kunfu; } void Study() { this->kunfu->Study(); } private: Kungfu* kunfu; };
- 测试代码如下
int test01() { Zhangshanfen* p = new Zhangshanfen(new TaiJiSword); p->Study(); return 0; }
- 根据构造器注入方式,当调用时,每次都要创建实例,那么如果张三丰是全局单例,则只能使用Setter注入方式。代码如下:
class Zhangshanfen { public: void setter(Kungfu* kungfu) { this->kungfu = kungfu; } void Study() { this->kungfu->Study(); } private: Kungfu* kungfu; };
- 测试端代码如下:
int test01() { Zhangshanfen* p = new Zhangshanfen(); p->setter(new TaiJiBoxing); p->Study(); return 0; }
- 最终得到UML类图如下:
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。