独望枫

人在尘世间,有缘自相见,变化千千万,未开窍,已迷恋
posts - 12, comments - 0, trackbacks - 0, articles - 1
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

设计模式之依赖倒置原则

Posted on 2016-07-10 15:59 小菜枫 阅读(60) 评论(0)  编辑 收藏 引用 所属分类: 学习笔记

依赖倒置原则:Dependence Inversion Principle,简称DIP。

定义:High level modules should not depend upon low level modules.Both should depend upon abstractions.

Abstractions should not depend upon details.

Details should depend upon abstractions。

翻译成中文如下:

  • 高层模块不应该依赖低层模块,两者都应该依赖抽象
  • 抽象不应该依赖细节
  • 细节应该依赖抽象

由来:Draw类依赖于Pic类,如果要将Draw类更改为依赖于Text类,则必定要修改Draw类才能达成目的。这种情况下,Draw类就是属于上面所提到的高层模块,Pic类和Text类是底层模块。

方案:将Draw类更改为依赖于接口I,Pic类和Text类各自实现接口I,Draw类通过接口I与Pic类/Text类发生关联。

例子:

原始版本:DrawManager类管理画图。

class Pic
{
public:
    Pic(void){};
    ~Pic(void){};

    void Draw()
    {
        cout<<"Pic ";
    }
};
class DrawManager
{
public:
    DrawManager(void){};
    ~DrawManager(void){};

    void Draw(Pic* objname)
    {
        objname->Draw();
        cout<<"is drawing.."<<endl;
    };
};

 

需求变更一版本:界面需要对文字进行绘制。

需求变更一版本之解决方案一:

class Pic
{
public:
    Pic(void){};
    ~Pic(void){};

    void Draw()
    {
        cout<<"Pic ";
    }
};
class Text
{
public:
    Text(void){};
    ~Text(void){};

    void Draw()
    {
        cout<<"Text ";
    }
};
class DrawManager
{
public:
    DrawManager(void){};
    ~DrawManager(void){};

    void Draw(Pic* objname)
    {
        objname->Draw();
        cout<<"is drawing.."<<endl;
    };

    void Draw(Text* objname)
    {
        objname->Draw();
        cout<<"is drawing.."<<endl;
    }
};

需求变更一版本之解决方案二:

class Obj
{
public:
    Obj(void){};
    ~Obj(void){};

    virtual void Draw() = 0;
};
class Pic:public Obj
{
public:
    Pic(void){};
    ~Pic(void){};

    virtual void Draw()
    {
        cout<<"Pic ";
    }
};
class Text:public Obj
{
public:
    Text(void){};
    ~Text(void){};

    virtual void Draw()
    {
        cout<<"Text ";
    }
};
class DrawManager
{
public:
    DrawManager(void){};
    ~DrawManager(void){};

    void Draw(Obj* objname)
    {
        objname->Draw();
        cout<<"is drawing.."<<endl;
    };
};

需求变更一版本之解决方案三:

#define interface struct
interface Obj
{
public:
    virtual void Draw()=0;
};
class Pic:public Obj
{
public:
    Pic(void){};
    ~Pic(void){};

    virtual void Draw()
    {
        cout<<"Pic ";
    }
};
class Text:public Obj
{
public:
    Text(void){};
    ~Text(void){};

    virtual void Draw()
    {
        cout<<"Text ";
    }
};
class DrawManager
{
public:
    DrawManager(void){};
    ~DrawManager(void){};

    void Draw(Obj* objname)
    {
        objname->Draw();
        cout<<"is drawing.."<<endl;
    };
};

总结

由上面的需求变更的三种实现方案,其中各自优缺如下:

方案一:不遵循依赖倒置原则
好处:新增加一个组件,客户端对应增加一个方法,简单明了
坏处:需要更改到DrawManager类

      后续增加新组件,DrawManager类每次都需要更改

方案二:遵循依赖倒置原则:基于抽象类
好处:后续新增组件不影响DrawManager类原有逻辑
      组件的实现变更不影响DrawManager类
      低耦合
坏处:增加一个text,缺增加了两个类(obj,text) 

方案三:如方案二(特别说明:c++实际没有interface,这里只是使用struct模拟interface使用)


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理