当前位置: 首页 > wzjs >正文

公文写作网站2024年重启核酸

公文写作网站,2024年重启核酸,wordpress ninety,山西本地网1. 依赖倒置 依赖倒置原则(Dependency Inversion Principle, DIP)是 SOLID 原则中的一项,其核心思想是通过抽象解耦高层模块和低层模块,使二者都依赖于抽象而非具体实现。 依赖反转/倒置的体现:传统依赖方向是高层模块…

1. 依赖倒置

依赖倒置原则(Dependency Inversion Principle, DIP)是 SOLID 原则中的一项,其核心思想是通过抽象解耦高层模块和低层模块,使二者都依赖于抽象而非具体实现

依赖反转/倒置的体现:传统依赖方向是高层模块直接调用低层模块,在源码级别上高层模块依赖低层细节模块。而 DIP 通过抽象反转这种依赖关系,使低层模块的实现在源码级别上依赖高层定义的抽象(视为高层模块的一部分)。

1.1 依赖倒置原则的核心

  1. 高层模块不直接依赖低层模块,二者都应依赖抽象(接口或抽象类,接口由高层模块定义,视为高层模块的一部分)。

  2. 抽象不依赖细节,细节(具体实现)应依赖抽象。

1.2 依赖倒置指导方针

  • 变量不可以持有具体类的引用——改用工厂,避免直接使用 new 持有具体类的引用(new 具体类的操作都封装到工厂中)

  • 不要让类派生自具体类——派生自抽象类或接口,这样就不依赖具体类了

  • 不要覆盖基类中已经实现的方法——如果这样,说明不是一个真正适合被继承的抽象

1.3 示例

场景

  • 高层模块 ReportGenerator 需要生成报告,依赖数据获取功能。

  • 低层模块 MySQLDatabase 和 SQLiteDatabase 提供具体的数据操作。

传统实现(未遵循 DIP)

// 低层模块:直接依赖具体实现
class MySQLDatabase {
public:void connect() { /* MySQL 连接逻辑 */ }std::string fetchData() { return "MySQL 数据"; }
};// 高层模块直接依赖低层具体类
class ReportGenerator {
private:MySQLDatabase db;  // 直接依赖具体实现
public:void generateReport() {db.connect();auto data = db.fetchData();std::cout << "报告数据: " << data << std::endl;}
};

问题ReportGenerator 直接依赖 MySQLDatabase,更换数据库(如改用 SQLite)需修改高层代码。

遵循 DIP 的实现

1、定义抽象接口

class Database {
public:virtual ~Database() = default;virtual void connect() = 0;virtual std::string fetchData() = 0;
};

2、低层模块实现接口

class MySQLDatabase : public Database {
public:void connect() override { /* MySQL 连接逻辑 */ }std::string fetchData() override { return "MySQL 数据"; }
};class SQLiteDatabase : public Database {
public:void connect() override { /* SQLite 连接逻辑 */ }std::string fetchData() override { return "SQLite 数据"; }
};

3、高层模块依赖抽象

class ReportGenerator {
private:Database& db;  // 依赖抽象接口
public:ReportGenerator(Database& database) : db(database) {}  // 依赖注入void generateReport() {db.connect();auto data = db.fetchData();std::cout << "报告数据: " << data << std::endl;}
};

class ReportGenerator {
private:Database& db;  // 依赖抽象接口
public:ReportGenerator(Database& database) : db(database) {}  // 依赖注入void generateReport() {db.connect();auto data = db.fetchData();std::cout << "报告数据: " << data << std::endl;}
};

4、使用示例

int main() {MySQLDatabase mysqlDb;SQLiteDatabase sqliteDb;ReportGenerator report1(mysqlDb);   // 使用 MySQLreport1.generateReport();ReportGenerator report2(sqliteDb);  // 使用 SQLitereport2.generateReport();return 0;
}

1.4 依赖倒置优势

  • 解耦:高层模块不依赖低层具体实现,可灵活替换数据库(如新增 MongoDB 只需实现 Database 接口)。

  • 可维护性:修改低层代码(如优化 MySQLDatabase)不影响高层模块。

  • 可测试性:可通过 Mock 对象(实现 Database 接口)轻松测试 ReportGenerator

1.5 依赖倒置小结

依赖倒置原则通过抽象解耦模块,使依赖关系从“高层 → 低层”变为“高层 → 抽象 ← 低层”,从而提升系统的灵活性和可维护性。在 C++ 中,可通过抽象类(接口)和依赖注入(如构造函数传入接口指针/引用)实现这一原则。

2. 依赖注入 DI

依赖注入(Dependency Injection, DI)是一种将对象依赖关系的外部化技术,其核心思想是:对象不直接创建或管理自己的依赖,而是由外部(调用者或框架)提供依赖的实例。通过这种方式,代码的耦合度降低,灵活性和可测试性显著提高。

2.1 依赖注入的本质

1、控制反转(IoC)

依赖注入是控制反转的一种实现方式。传统代码中,对象自己控制依赖的创建(如 new 一个具体类),而依赖注入将这一控制权交给外部,实现“依赖被注入到对象中”。

2、依赖抽象而非实现

依赖注入通常结合接口或抽象类使用,确保对象依赖的是抽象,而非具体实现(符合依赖倒置原则)。

2.2 依赖注入的三种方式

1. 构造函数注入(最常用)

通过构造函数传递依赖,确保对象在创建时即具备完整依赖。

class NotificationService {
private:MessageSender& sender;  // 依赖抽象接口
public:NotificationService(MessageSender& sender) : sender(sender) {}  // 构造函数注入void sendMessage(const std::string& msg) {sender.send(msg);}
};

2. 属性注入(Setter 注入)

通过公开的成员属性或 Setter 方法动态设置依赖。

class NotificationService {
public:void setSender(MessageSender& sender) {  // Setter 注入this->sender = &sender;}
private:MessageSender* sender;
};

3. 方法注入

通过方法参数传递依赖,适用于临时或局部依赖。

class NotificationService {
public:void sendMessage(MessageSender& sender, const std::string& msg) {  // 方法注入sender.send(msg);}
};

2.3 为什么需要依赖注入?

1. 解耦与可维护性

  • 传统代码:对象内部直接创建依赖,导致紧耦合。

class UserService {
private:
MySQLDatabase db; // 直接依赖具体类
};


若需改用 `SQLiteDatabase`,必须修改 `UserService` 的代码。- **依赖注入**:通过接口解耦,仅需注入不同实现。```cpp
class UserService {
private:Database& db;  // 依赖抽象
public:UserService(Database& db) : db(db) {}
};

2. 可测试性

  • 依赖注入允许在测试时替换为 Mock 对象。

class MockDatabase : public Database { /* 模拟实现 */ };TEST(UserServiceTest) {MockDatabase mockDb;UserService service(mockDb);  // 注入 Mock 对象// 执行测试...
}

3. 扩展性
  • 新增功能时,只需实现新依赖并注入,无需修改现有代码。

class MongoDB : public Database { /* 新数据库实现 */ };MongoDB mongoDb;
UserService service(mongoDb);  // 直接注入新依赖

2.4 C++ 依赖注入的实践技巧

1. 使用智能指针管理生命周期

避免裸指针导致的内存泄漏,使用 std::shared_ptr 或 std::unique_ptr

class NotificationService {
private:std::shared_ptr<MessageSender> sender;  // 智能指针管理依赖
public:NotificationService(std::shared_ptr<MessageSender> sender) : sender(sender) {}
};

2. 结合工厂模式

通过工厂类集中管理依赖的创建逻辑。

class SenderFactory {
public:static std::shared_ptr<MessageSender> createSender(const std::string& type) {if (type == "email") return std::make_shared<EmailSender>();else return std::make_shared<SmsSender>();}
};// 使用工厂创建依赖
auto sender = SenderFactory::createSender("email");
NotificationService service(sender);

3. 依赖注入容器(IoC Container)

在复杂项目中,使用容器自动管理依赖关系(如 Boost.DI)。

#include <boost/di.hpp>
namespace di = boost::di;// 定义接口和实现
class Database { /* ... */ };
class MySQLDatabase : public Database { /* ... */ };// 配置容器
auto injector = di::make_injector(di::bind<Database>().to<MySQLDatabase>()
);// 自动注入依赖
class UserService {
public:UserService(Database& db) { /* ... */ }
};
UserService service = injector.create<UserService>();

2.5 依赖注入的常见误区

1、依赖注入 ≠ 工厂模式

工厂模式负责创建对象,而依赖注入负责传递对象。二者常结合使用,但目的不同。

2、依赖注入 ≠ 必须用框架

即使不用框架(如 Boost.DI),通过构造函数或参数传递依赖,也能实现依赖注入。

3、过度注入问题

若一个类需要注入过多依赖(如超过 4 个),可能设计存在问题,需考虑拆分职责。

2.6 依赖注入小结

  • 依赖注入的核心:将依赖的创建和绑定从对象内部转移到外部。

  • 核心价值:解耦、可测试、可扩展。

C++ 实现关键:

通过接口抽象依赖。

使用构造函数/智能指针传递依赖。

结合工厂模式或 IoC 容器管理复杂依赖关系。

3. 控制反转 IoC

IoC(Inversion of Control,控制反转) 是一种软件设计原则,其核心思想是将程序流程的控制权从开发者转移给框架或容器,以降低代码的耦合度,提高模块化和可维护性。它是实现依赖倒置原则(DIP)的关键机制,也是现代框架(如 Spring、.NET Core)和依赖注入(DI)容器的基础。

3.1 控制反转 IoC vs. 依赖注入 DI

  • IoC(控制反转):广义的设计原则,表示控制权转移的范式。其本质是将程序流程的控制权从开发者转移到框架或容器

  • DI(依赖注入):IoC 的一种具体实现技术,通过外部传递依赖。

关系

  • 依赖注入是控制反转的实现方式之一。

  • 控制反转还可以通过模板方法、回调(关联:好莱坞原则)等方式实现。

  • 使用 IoC 容器(如 Boost.DI)自动管理复杂依赖关系。

4. 工厂模式

尽管依赖倒置和依赖注入都强调面向抽象编程,但在实际编码中仍需创建(new)具体底层组件(ConcreteClass)

工厂模式主要分为三种,严格来说包括 简单工厂模式工厂方法模式 和 抽象工厂模式。以下是它们的核心区别、适用场景及 C++ 示例:

4.1 简单工厂模式(Simple Factory)

有时候简单工厂不被视为正式的设计模式,而是一个编程习惯。

核心思想

  • 通过一个工厂类,根据传入的参数决定创建哪种具体产品对象。

  • 不符合开闭原则(新增产品需修改工厂类逻辑)。

适用场景

  • 产品类型较少且创建逻辑简单。

  • 不需要频繁扩展新类型。

C++ 示例

// 抽象产品
class Shape {
public:virtual void draw() = 0;virtual ~Shape() = default;
};// 具体产品
class Circle : public Shape {
public:void draw() override { std::cout << "画一个圆形" << std::endl; }
};class Square : public Shape {
public:void draw() override { std::cout << "画一个正方形" << std::endl; }
};// 简单工厂类
class ShapeFactory {
public:static Shape* createShape(const std::string& type) {if (type == "circle") return new Circle();else if (type == "square") return new Square();else return nullptr;}
};// 使用示例
int main() {Shape* circle = ShapeFactory::createShape("circle");circle->draw();  // 输出: 画一个圆形delete circle;return 0;
}

4.2 工厂方法模式(Factory Method)

核心思想
  • 定义一个创建对象的抽象方法,由子类决定实例化哪个类。

  • 符合开闭原则(新增产品只需新增子类工厂)。

适用场景
  • 产品类型可能频繁扩展。

  • 需要将对象创建延迟到子类。

C++ 示例

// 抽象产品
class Database {
public:virtual void connect() = 0;virtual ~Database() = default;
};// 具体产品
class MySQL : public Database {
public:void connect() override { std::cout << "连接到 MySQL" << std::endl; }
};class PostgreSQL : public Database {
public:void connect() override { std::cout << "连接到 PostgreSQL" << std::endl; }
};// 抽象工厂
class DatabaseFactory {
public:virtual Database* createDatabase() = 0;virtual ~DatabaseFactory() = default;
};// 具体工厂
class MySQLFactory : public DatabaseFactory {
public:Database* createDatabase() override { return new MySQL(); }
};class PostgreSQLFactory : public DatabaseFactory {
public:Database* createDatabase() override { return new PostgreSQL(); }
};// 使用示例
int main() {DatabaseFactory* factory = new PostgreSQLFactory();Database* db = factory->createDatabase();db->connect();  // 输出: 连接到 PostgreSQLdelete db;delete factory;return 0;
}

4.3 抽象工厂模式(Abstract Factory)

核心思想
  • 提供一个接口,用于创建相关或依赖对象族,而无需指定具体类。

  • 抽象工厂包含多个工厂方法,每个方法负责创建一个产品族中的对象。

适用场景
  • 需要创建一组相关或依赖的对象(例如 GUI 组件:按钮、文本框、下拉菜单等)。

  • 系统需要独立于产品的创建、组合和表示。

C++ 示例

// 抽象产品:按钮
class Button {
public:virtual void render() = 0;virtual ~Button() = default;
};// 具体产品:Windows 按钮
class WindowsButton : public Button {
public:void render() override { std::cout << "Windows 风格按钮" << std::endl; }
};// 具体产品:MacOS 按钮
class MacOSButton : public Button {
public:void render() override { std::cout << "MacOS 风格按钮" << std::endl; }
};// 抽象产品:文本框
class TextBox {
public:virtual void display() = 0;virtual ~TextBox() = default;
};// 具体产品:Windows 文本框
class WindowsTextBox : public TextBox {
public:void display() override { std::cout << "Windows 风格文本框" << std::endl; }
};// 具体产品:MacOS 文本框
class MacOSTextBox : public TextBox {
public:void display() override { std::cout << "MacOS 风格文本框" << std::endl; }
};// 抽象工厂
class GUIFactory {
public:virtual Button* createButton() = 0;virtual TextBox* createTextBox() = 0;virtual ~GUIFactory() = default;
};// 具体工厂:Windows 风格组件
class WindowsFactory : public GUIFactory {
public:Button* createButton() override { return new WindowsButton(); }TextBox* createTextBox() override { return new WindowsTextBox(); }
};// 具体工厂:MacOS 风格组件
class MacOSFactory : public GUIFactory {
public:Button* createButton() override { return new MacOSButton(); }TextBox* createTextBox() override { return new MacOSTextBox(); }
};// 使用示例
int main() {GUIFactory* factory = new MacOSFactory();Button* button = factory->createButton();button->render();  // 输出: MacOS 风格按钮TextBox* textBox = factory->createTextBox();textBox->display(); // 输出: MacOS 风格文本框delete button;delete textBox;delete factory;return 0;
}

4.4 三种工厂模式对比

4.5 工厂模式小结

  • 简单工厂:适合简单场景,但违背开闭原则。

  • 工厂方法:解决单一产品的扩展问题。

  • 抽象工厂:解决多产品族的创建问题,强调产品之间的关联性。

根据需求选择合适模式:若产品单一且可能扩展,用工厂方法;若需创建一组关联对象,用抽象工厂;若产品类型固定且简单,用简单工厂。

5. 总结

依赖倒置(DIP)、依赖注入(DI)、控制反转(IoC)和工厂模式是软件设计中紧密相关的概念,它们共同服务于代码的解耦和可维护性。

5.1 关联

  • 依赖倒置原则(Dependency Inversion Principle, DIP):高层模块不依赖低层模块,两者都依赖抽象(接口或抽象类)。该思想指导工厂模式、DI 和 IoC 的设计方向。

  • 控制反转(Inversion of Control, IoC):将对象的创建和生命周期管理权从程序内部转移给外部容器(如框架)。例如:依赖由外部容器(如工厂或框架)创建并注入,而不是直接创建依赖。工厂模式和依赖注入 DI 是实现 IoC 的具体方式。

  • 依赖注入(Dependency Injection, DI):通过构造函数、Setter 或接口,将依赖对象被动传递给使用方。是实现 IoC 的具体技术手段。工厂模式常用于生成这些依赖对象。

  • 工厂模式(Factory Pattern):封装具体对象创建逻辑,通过工厂类统一创建对象。是实现 IoC 的手段之一,隐藏实例化细节,支持 DIP 和 DI。是依赖注入 DI 和控制反转 IoC 的底层支撑。

四者共同目标是解耦代码,提升扩展性和可维护性。

5.2 示例全链路

// 1. 遵循 DIP:定义抽象接口
class IStorage { /* ... */ };// 2. 具体实现
class DatabaseStorage : public IStorage { /* ... */ };// 3. 工厂模式:封装对象创建
class StorageFactory {
public:static IStorage* createStorage() { return new DatabaseStorage(); }
};// 4. 依赖注入:通过构造函数传递对象
class UserService {
private:IStorage* storage;
public:UserService(IStorage* storage) : storage(storage) {}
};// 5. 控制反转:由工厂创建依赖,而非 UserService 内部创建
int main() {IStorage* storage = StorageFactory::createStorage();UserService userService(storage); // DI 注入userService.saveUser();delete storage;return 0;
}

文章转载自:Zijian/TENG

原文链接:依赖倒置 DIP、依赖注入 DI、控制反转 IoC 和工厂模式 - Zijian/TENG - 博客园

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

http://www.dtcms.com/wzjs/96816.html

相关文章:

  • 网站建设新手市场营销方案范文
  • 精美网站制作百度快速收录办法
  • 做试客刷单的网站有哪些百度指数名词解释
  • 寿光网站建设宁波优化关键词首页排名
  • 淘宝券商城网站制作郑州专业网站建设公司
  • 网站建设投票系统设计百度seo关键词优化
  • 又拍云 wordpress使用北京专门做seo
  • 哪些网站可以做产品推广推广引流图片
  • 自己做网站卖衣服最新全国疫情实时大数据
  • 网站开发常用形状代推广平台
  • 龙岩网上通缉犯名单查询企业关键词排名优化网址
  • 宁波江北建设局网站百度知道官网
  • 无网站做cpa站长之家工具查询
  • 中国英文政务网站建设域名备案
  • 软件工程属于什么专业类别淘宝seo是什么意思啊
  • 房产网站建设价格哪里可以做
  • 怒江北京网站建设网络推广需要多少钱
  • 展馆展示设计公司招聘信息seo技术分享博客
  • 找生产厂家的网站网络推广外包公司排名
  • 东莞网站设计服务全网搜索软件
  • 网站会员收费怎么做网站免费发布与推广
  • 呼伦贝尔网站建设平台域名注册查询官网
  • 北京品牌网站开发atp最新排名
  • 网站前期建设浅谈一下网络营销的几个误区
  • 青岛工商注册核名查询系统郑州百度seo关键词
  • 喊别人做的网站不肯给代码百度app推广方法
  • 哈尔滨网站建设效果好教育培训机构官网
  • 网站及邮件系统建设合肥seo推广公司
  • 郑州公司网站建设服务一个自己的网站
  • 公司网站建设的视频教程百度推广多少钱