面向对象设计原则实践OA开心乐园源码下载.之二.依赖倒转原则

某系统提供一OA开心乐园源码下载联系方式:QQ:2747044651 网址http://zhengtuwl.com 个数据转换模块,可以将来自不同数据源的数据转换成多种格式,如,

可以转换来自数据库的数据(DatabaseSource)、也可以转换来自文本文件的数据(TextSource),

转换后的格式可以是XML文件(XMLTransformer)、也可以是XLS文件(XLSTransformer)

依赖倒转原则-图-1

依赖倒转原则-图-2

图(一)和图(二)分析:

因为该系统可能需要增加新的数据源或者新的文件格式,

(图一)中,每增加一个新的类型的数据源或者新的类型的文件格式,

客户类MainClass都需要修改源代码,以便使用新的类,这违背了开闭原则。

(图二)使用依赖倒转原则对其进行重构:

a) 客户类MainClass 依赖于两个抽象类变量: AbstractSource, AbstractTransformer;

其中,抽象类AbstractSource的子类 DatatbaseSource , TextSource是不同输出入源的实现;

抽象类AbstractTransformer的子类XMLTransformer, XLSTransformer是不同输出格式的实现。

而客户类通过配置文件config.xml来确定到底如何处理数据;

  1. 实例二
    反面例子:

缺点:耦合太紧密,Light发生变化将影响ToggleSwitch。

解决办法一:

将Light作成Abstract,然后具体类继承自Light。

优点:ToggleSwitch依赖于抽象类Light,具有更高的稳定性,

而BulbLight与TubeLight继承自Light,可以根据"开放-封闭"原则进行扩展。

只要Light不发生变化,BulbLight与TubeLight的变化就不会波及ToggleSwitch。

缺点:如果用ToggleSwitch控制一台电视就很困难了。

总不能让TV继承自Light吧。

解决方法二:

优点:更为通用、更为稳定。

上面的计算器例子用这个原则更进一步的优化的代码如下:

#include <stdio.h>

#include <stdlib.h>

#include <iostream>

#include <string>

using namespace std;

/* Step1:

  • 使用vitual定义函数的功能模块,相当于实现公共界面设计
    */

class IGetResult {

public:

//virtual double get_result(double numberA, double numberB) = 0;

virtual double get_result() = 0;

public:

/ 注意一定要不要忘记添加虚析构函数 /

virtual ~IGetResult(){}

};

/* Step2 :

  • 继承基类,定义具体的功能模块,并声明具体需要的私有成员变量
  • 实现具体的功能模块
    */

class Add : public IGetResult {

public:

Add(double a, double b){

std::cout << "Add" << endl;

m_numberA = a;

m_numberB = b;

};

~Add(void) {};

public:

double get_result();

private:

double m_numberA;

double m_numberB;

};

/ 实现具体的功能模块 /

double Add::get_result() {

std::cout << "Add::get_result()" << endl;

return m_numberA + m_numberB;

}

class Del : public IGetResult {

public:

Del(double a, double b){

std::cout << "Del" << endl;

m_numberA = a;

m_numberB = b;

};

virtual ~Del(void) {};

public:

double get_result();

private:

double m_numberA;

double m_numberB;

};

double Del::get_result(){

std::cout << "Del::get_result()" << endl;

return m_numberA - m_numberB;

}

class Mul: public IGetResult {

public:

Mul(double a, double b){

std::cout << "Mul" << endl;

m_numberA = a;

m_numberB = b;

};

virtual ~Mul(void) {};

public:

double get_result();

private:

double m_numberA;

double m_numberB;

};

double Mul::get_result(){

std::cout << "Mul::get_result()" << endl;

return m_numberA * m_numberB;

}

/* Step4:

  • 将功能函数接口注入封装类中
    */

class MainOperate {

public:

MainOperate(IGetResult *get_result_ptr){

this->m_get_result = get_result_ptr;

}

public:

double Operate();

private:

IGetResult *m_get_result;

};

/ 实现封装类中的接口函数的具体调用方式 /

double MainOperate::Operate(){

double ret = 0;

ret = this->m_get_result->get_result();

return ret;

}

int main(int argc, char* argv[]){

std::cout << "main()" << endl;

int a = 22;

int b = 10;

int ret = 0;

/ Step5: 主函数中定义调用模块接口函数/

IGetResult *get_result = new Add(a, b);

/ Step6: 主函数调用封装类中接口函数/

MainOperate *main_operate = new MainOperate(get_result);

ret = main_operate->Operate();

std::cout << "ret = " << ret << endl;

delete get_result;

get_result = new Del(a, b);

main_operate = new MainOperate(get_result);

ret = main_operate->Operate();

std::cout << "ret = " << ret << endl;

delete get_result;

get_result = new Mul(a, b);

main_operate = new MainOperate(get_result);

ret = main_operate->Operate();

std::cout << "ret = " << ret << endl;

delete get_result;

/
Add add = Add(a, b);
ret = add.get_result();
std::cout << "ret = " << ret << endl;
Del del = Del(a, b);
ret = del.get_result();
std::cout << "ret = " << ret << endl;
/

return 0;

}
特点:

代码要依赖于抽象的类,而不要依赖于具体的类;

针对接口或抽象类编程,而不是针对具体类编程。

实现了接口注入;

  1. 总结
    高层模块不应该依赖底层模块,两个都应该依赖与抽象;

抽象不应该依赖于细节,细节应该依赖于抽象。

客户端与实现类通过抽象类进行耦合。

DIP优点:

使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略受到细节改变的影响。

依赖倒置原则使细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性。

DIP注意点:

1)、任何变量都不应该持有一个指向具体类的指针或者引用

2)、任何类都不应该从具体类派生(始于抽象,来自具体)

3)、任何方法都不应该覆写它的任何基类中的已经实现了的方法

阅读更多
程序猿必关注这个技术,风头正劲,仅4个月薪酬45K
大数据技术与运用的成熟,应用集中于互联网、金融、医疗、新能源、通信和房地产等行业。整理平均薪资情况和大数据学习大纲供

猜你喜欢

转载自blog.51cto.com/13941184/2164734