依赖倒转原则强调针对接口编程,依赖于抽象而不依赖于具体。也就是说高层模块不应该依赖于低层模块,而是二者都应该依赖于抽象接口层。
依赖倒转原则的目的在于把高层次组件和低层次组件解耦,高层次组件依赖于接口层实现,低层次组件也依赖于接口层实现,通过这种方式以谋求重用不同的低层组件的实现。
以下的代码案例以组装电脑这一场景进行举例说明:
Computer.h
#pragma once
#include<iostream>
#include<string>
class HardDisk
{
public:
explicit HardDisk(void) {};
explicit HardDisk(std::string name) :m_hardDiskName(name) {};
virtual~HardDisk(void) { std::cout << "~HardDisk" << std::endl; };
virtual bool HardDiskWork(void) = 0;
bool setHardDiskName(std::string name) { m_hardDiskName = name; return true; }
const std::string getHardDiskName(void) const { return m_hardDiskName; }
private:
std::string m_hardDiskName;
protected:
};
class Memory
{
public:
explicit Memory(void) {};
explicit Memory(std::string name) :m_memoryName(name) {};
virtual~Memory(void) { std::cout << "~Memory(void)" << std::endl; };
virtual bool MemoryWork() = 0;
bool setMemoryName(std::string name) { m_memoryName = name; return true; }
const std::string getMemoryName(void) const { return m_memoryName; }
private:
std::string m_memoryName;
protected:
};
class Cpu
{
public:
explicit Cpu(void) {};
explicit Cpu(std::string name) :m_cpuName(name) {};
virtual~Cpu(void) { std::cout << "~Cpu(void)" << std::endl; };
virtual bool CpuWork() = 0;
bool setCpuName(std::string name) { m_cpuName = name; return true; }
const std::string getCpuName(void)const { return m_cpuName; }
private:
std::string m_cpuName;
protected:
};
// 需要让Computer的框架和具体的硬件进行解耦和就需要抽象出一个接口层
class Computer
{
public:
explicit Computer(void);
explicit Computer(std::string name) :m_computerName(name) {};
explicit Computer(std::string name,HardDisk* hardDisk,Memory* memory, Cpu* cpu)
:m_computerName(name), m_hardDisk(hardDisk), m_memory(memory), m_cpu(cpu){};
// 拷贝构造、赋值构造、move语义构造一般都应该给出
virtual~Computer(void);
bool setComputerName(std::string name) { m_computerName = name; return true; };
const std::string getComputerName(void)const { return m_computerName; };
bool setHardDisk(HardDisk* hardDisk) { m_hardDisk = hardDisk; return true; };
const HardDisk* getHardDisk(void) const { return m_hardDisk; };
bool setMemory(Memory* memory) { m_memory = memory; return true; };
const Memory* getMemory(void) const { return m_memory; };
bool setCpu(Cpu* cpu) { m_cpu = cpu; return true; };
const Cpu* getCpu(void)const { return m_cpu; };
// Computer类定义的对象的默认Working方式,继承的类可以重写该方法
virtual bool computerWorking(void)
{
std::cout << this->getComputerName()<< std::endl;
std::cout<< this->m_hardDisk->getHardDiskName();
this->m_hardDisk->HardDiskWork();
std::cout << this->m_memory->getMemoryName();
this->m_memory->MemoryWork();
std::cout << this->m_cpu->getCpuName();
this->m_cpu->CpuWork();
return true;
};
private:
std::string m_computerName= "Computer";
HardDisk* m_hardDisk= nullptr; // 定义抽象成员,不直接定义具体类,通过定义抽象类达到解耦和
Memory* m_memory = nullptr;
Cpu* m_cpu = nullptr;
};
// 具体硬件类设计
class WDHardDisk :public HardDisk // 西部数据硬盘
{
public:
bool HardDiskWork(void) { std::cout << "WDHardDisk::HardDiskWork(void) " << std::endl; return true;}; // 接口实现
};
class SeagateHardDisk :public HardDisk // 希捷硬盘
{
public:
bool HardDiskWork(void) { std::cout << "SeagateHardDisk::HardDiskWork(void)" << std::endl; return true;}; // 接口实现
};
class SamsungMemory :public Memory // 三星内存
{
public:
bool MemoryWork(void) { std::cout << "SamsungMemory::MemoryWork(void)" << std::endl; return true;}; // 接口实现
};
class MicronMemory :public Memory // 镁光内存
{
public:
bool MemoryWork(void) { std::cout << "MicronMemory::MemoryWork(void)" << std::endl; return true;}; // 接口实现
};
class InterCpu :public Cpu // Inter CPU
{
public:
bool CpuWork(void) { std::cout << "InterCpu::CpuWork(void) " << std::endl; return true; }; // 接口实现
};
class AMDCpu :public Cpu // AMD CPU
{
public:
bool CpuWork(void) { std::cout << "AMDCpu::CpuWork(void) " << std::endl; return true;}; // 接口实现
};
Computer.cpp
#include "Computer.h"
Computer::Computer()
{
}
Computer::~Computer()
{
delete m_hardDisk;
delete m_memory;
delete m_cpu;
}
mainTest.cpp
#include<iostream>
#include"Computer.h"
using namespace std;
int main(void)
{
// 依赖倒置原则指的是:
//1、高层次的模块(框架层)不应该依赖于低层次的模块(实现层),他们都应该依赖于抽象(接口、协议层)。
//2、抽象(接口)不应该依赖于具体实现(实现层),具体实现(实现层)应该依赖于抽象(接口、协议层)。
// 这么做的目的是实现业务层(业务层最好应该构建在框架之上,至少也要是接口层以上)和实现层的解耦和以及实现层间的解耦和。
Computer myComputer("个人超级本",new WDHardDisk(),new SamsungMemory(),new InterCpu());
myComputer.computerWorking();
Computer myComputer2("良好本", new SeagateHardDisk(), new MicronMemory(), new AMDCpu());
myComputer2.computerWorking();
Computer* myComputer3 = new Computer();
delete myComputer3;
myComputer3 = nullptr;
system("pause");
return 0;
}