说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

关于依赖倒置原则的依赖问题

编辑:说三道四文库 发布时间:2018-08-20 04:22
HTML文档下载 WORD文档下载 PDF文档下载
经典例子是开关电灯例子

我现在换成总经理和秘书的情况,其实一样。

强耦合阶段:

总经理  依赖  秘书

即总经理类中有私有成员变量 秘书
秘书改变,则意味着总经理类需要改变。这是不好的设计。
依赖倒转告诉我们说高层不应该依赖低层,二者都应该依赖抽象

那么现在让总经理也依赖抽象,让秘书也依赖抽象,因此定义一个抽象类:比如员工类


class Iemployee
{
virtual void Interpret()=0;//秘书能翻译
virtual void Carry()=0;//助理能拎包
virtual void Drive()=0;//司机能开车
virtual void Design()=0;//设计师能设计新产品
virtual void Record()=0;//员工在开会的时候都需要做记录
};


用秘书类,助理类,司机类,设计师类 继承于这个抽象类,并实现该类。

这样达到了总经理也依赖抽象,秘书也依赖抽象了。如果换了秘书,比如一个女秘书换成了男秘书,直接修改秘书类就可以了,而不用去修改抽象类接口以及总经理类,达到了依赖倒转原则的目的。
但是在C++实现中,有个问题是如果总经理类中有Iemployee这样一个成员变量,Iemployee类是抽象类,抽象类是不能够实例化的。

对于这样的问题如何解决?
请高手指点,或者我对依赖倒转原则的理解有偏差?
抽象类自然是不可以实例化的,但是可以引用抽象类的指针用来指向派生类对象。
楼上能否说的具体点?比如弄个例子?

class Iemployee 

virtual void Interpret()=0;//秘书能翻译  
virtual void Carry()=0;//助理能拎包  
virtual void Drive()=0;//司机能开车  
virtual void Design()=0;//设计师能设计新产品  
virtual void Record()=0;//员工在开会的时候都需要做记录 
};

这样肯定是不行的
class manage:Iemployee 
{
  Iemployee ie;
};

但是这样是可以的
class manage:Iemployee 
{
  Iemployee *ie;
};


当然我不知道这上面的回答是否符合你的要求,如果不是,我建议你将你需要实现的结构贴出来,那样我们就可以为你分析并且改进你的结构,然后就可以符合你的工程了。
不是那个意思。是这样的:


class Iemployee 

virtual void Interpret()=0;//秘书能翻译  
virtual void Carry()=0;//助理能拎包  
virtual void Drive()=0;//司机能开车  
virtual void Design()=0;//设计师能设计新产品  
virtual void Record()=0;//员工在开会的时候都需要做记录 
};

//--------------------------------------------------//
class Secretary : public Iemployee
{
public:
void Interpret(){cout<<"帮助总经理翻译!"<<endl;}
void Carry(){cout<<"帮助总经理拿东西!"<<endl;}
};
//--------------------------------------------------//
class Driver : public Iemployee
{
public:
void Drive(){cout<<"给总经理开车"<<endl;}
void Carry(){cout<<"帮助总经理拿东西!"<<endl;}
};
//--------------------------------------------------//
class Stylist : public Iemployee
{
public:
void Design(){cout<<"给公司设计新产品"<<endl;}
};
//--------------------------------------------------//
class Boss
{
Iemployee *aIemployee;
public:
void Negotiate();
void HoldMetting();
void InCompany();
};
void Boss::HoldMetting()
{
Secretary aSecretary;
aSecretary.Carry();
}
void Boss::Negotiate()
{
//aIemployee.Interpret();//让其访问继承类而非抽象类。
}
void Boss::InCompany()
{
aIemployee->Record();
}
//--------------------------------------------------//
void main()
{
Boss aBoss;
aBoss.HoldMetting();
aBoss.Negotiate();
aBoss.InCompany();
}

可以继承Iemployee,自己来写一个具体的employee,然后用这个指针指向具体的对象……
建议看看strategy模式,这个模式能帮解决根本问题~
class Iemployee
{
    virtual void Interpret()=0;//秘书能翻译
    virtual void Carry()=0;//助理能拎包
    virtual void Drive()=0;//司机能开车
    virtual void Design()=0;//设计师能设计新产品
    virtual void Record()=0;//员工在开会的时候都需要做记录
};

你這個設計讓 秘書也必須實現Interpret之外的, 助理也必須要實現Carry之外的,合理么? 

class Iemployee
{
  virtual void Do() = 0;
};
秘書自然會提包,司機自然會開車, people.Do(); //做事
這樣呢

你這個例子感覺有點..
經理沒必要從接口繼承

class boss
{
   Imeplyee* DoSomething(Iemployee* proxy)
   {
      proxy.Do();
      return proxy;
   }
};

boss b;
Imeplyee* p = b.DoSomething(new Secretary);
delete p;

個人觀點而已,可能跟你理解的不一樣 
我是按依赖倒转原则搞出来的东西,搞出来就这个样子了,感觉是有点恶心。
我就觉得是不是我理解的不到位。
另外,实现接口的时候肯定是要实现其他的虚函数的,所以不合理啊。。。
疑惑。
顶一下,内容太短,还短?
根据楼主所贴代码而已看出,是接口没有分离好,Iemployee 接口具备的应该是派生类所具备的共性,此处lz可以设计一个Iemployee 空类,里面什么都没有,这样效果是一样的。

class Iemployee 

};

//--------------------------------------------------//
class Secretary : public Iemployee
{
public:
    void Interpret(){cout<<"帮助总经理翻译!"<<endl;}
    void Carry(){cout<<"帮助总经理拿东西!"<<endl;}
};
//--------------------------------------------------//
class Driver : public Iemployee
{
public:
    void Drive(){cout<<"给总经理开车"<<endl;}
    void Carry(){cout<<"帮助总经理拿东西!"<<endl;}
};
//--------------------------------------------------//
class Stylist : public Iemployee
{
public:
    void Design(){cout<<"给公司设计新产品"<<endl;}
};
//--------------------------------------------------//
class Boss
{
    Iemployee *aIemployee;
public:
    void Negotiate();
    void HoldMetting();
    void InCompany();
};

lz上面的实现方式是有问题的,基础虚基类的派生类如果没有实现基类的所有函数的话,本身还是虚拟类,但是上面的改进是可以的了
具体使用Iemployee的时候就必须具体转换为具体的对象了
重新设计了一下,发现这样貌似符合依赖倒转原则?我自己不确定是不是符合该原则。。。
有不对的地方请大侠们指点:
//--------------------------------------------------//
class Iemployee
{
public:
virtual void Work()=0;
};
//--------------------------------------------------//
class Secretary : public Iemployee
{
public:
void Interpret(){cout<<"帮助总经理翻译!"<<endl;}
void Carry(){cout<<"帮助总经理拿东西!"<<endl;}
void Work(){cout<<"秘书工作"<<endl;}
};
//--------------------------------------------------//
class Driver : public Iemployee
{
public:
void Drive(){cout<<"给总经理开车"<<endl;}
void Carry(){cout<<"帮助总经理拿东西!"<<endl;}
void Work(){cout<<"司机工作"<<endl;}
};
//--------------------------------------------------//
class Stylist : public Iemployee
{
public:
void Design(){cout<<"给公司设计新产品"<<endl;}
void Work(){cout<<"设计师工作"<<endl;}
};
//--------------------------------------------------//
class Boss
{
public:
void Negotiate(Iemployee *aIemployee);
void HoldMetting(Iemployee *aIemployee);
void InCompany(Iemployee *aIemployee);
};
void Boss::HoldMetting(Iemployee *aIemployee)
{
aIemployee->Work();
}
void Boss::Negotiate(Iemployee *aIemployee)
{
aIemployee->Work();
}
void Boss::InCompany(Iemployee *aIemployee)
{
aIemployee->Work();
}
//--------------------------------------------------//
void main()
{
Boss aBoss;
Iemployee *aIemployeeSecretary = new Secretary();
Iemployee *aIemployeeStylist = new Stylist();
Iemployee *aIemployeeDriver = new Driver();
aBoss.HoldMetting(aIemployeeSecretary);
        //aIemployeeSecretary->Carry(); 具体的工作是否可以放在这里?但是我这里aIemployeeSecretary 已经变为Iemployee 类型,将没有Carry()成员函数,这个问题怎么解决?
aBoss.Negotiate(aIemployeeStylist);
aBoss.InCompany(aIemployeeDriver);
delete aIemployeeSecretary;
delete aIemployeeStylist;
delete aIemployeeDriver;
}


//--------------------------------------------------//
依赖倒置就是依赖抽象,而不依赖具体类
面向接口编程,大概就这意思
楼上说的真对。。。。
你的基类设计就有问题,public继承意味着is-a,但你没有做到这一点,你的Iemployee是一个无所不能的类,从本质上来讲应该叫superman类,但Secretary呢?driver呢?他们是全能的么?那凭什么让他们public继承自superman呢?
引用 15 楼  的回复:
你的基类设计就有问题,public继承意味着is-a,但你没有做到这一点,你的Iemployee是一个无所不能的类,从本质上来讲应该叫superman类,但Secretary呢?driver呢?他们是全能的么?那凭什么让他们public继承自superman呢?


讲的很是霸气,那要怎么设计才合理,求指导
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘