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

redoffice 2010-02-24 03:53:29
经典例子是开关电灯例子

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

强耦合阶段:

总经理 依赖 秘书

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

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


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类是抽象类,抽象类是不能够实例化的。

对于这样的问题如何解决?
请高手指点,或者我对依赖倒转原则的理解有偏差?
...全文
354 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
lqz1988 2012-10-29
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]
你的基类设计就有问题,public继承意味着is-a,但你没有做到这一点,你的Iemployee是一个无所不能的类,从本质上来讲应该叫superman类,但Secretary呢?driver呢?他们是全能的么?那凭什么让他们public继承自superman呢?
[/Quote]

讲的很是霸气,那要怎么设计才合理,求指导
atrend440 2010-04-22
  • 打赏
  • 举报
回复
你的基类设计就有问题,public继承意味着is-a,但你没有做到这一点,你的Iemployee是一个无所不能的类,从本质上来讲应该叫superman类,但Secretary呢?driver呢?他们是全能的么?那凭什么让他们public继承自superman呢?
redoffice 2010-03-01
  • 打赏
  • 举报
回复
楼上说的真对。。。。
redoffice 2010-02-26
  • 打赏
  • 举报
回复
重新设计了一下,发现这样貌似符合依赖倒转原则?我自己不确定是不是符合该原则。。。
有不对的地方请大侠们指点:
//--------------------------------------------------//
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;
}


//--------------------------------------------------//
houzui 2010-02-26
  • 打赏
  • 举报
回复
依赖倒置就是依赖抽象,而不依赖具体类
面向接口编程,大概就这意思
redoffice 2010-02-25
  • 打赏
  • 举报
回复
顶一下,内容太短,还短?
redoffice 2010-02-25
  • 打赏
  • 举报
回复
我是按依赖倒转原则搞出来的东西,搞出来就这个样子了,感觉是有点恶心。
我就觉得是不是我理解的不到位。
另外,实现接口的时候肯定是要实现其他的虚函数的,所以不合理啊。。。
疑惑。
Qlaiaqu 2010-02-25
  • 打赏
  • 举报
回复
具体使用Iemployee的时候就必须具体转换为具体的对象了
Qlaiaqu 2010-02-25
  • 打赏
  • 举报
回复
根据楼主所贴代码而已看出,是接口没有分离好,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上面的实现方式是有问题的,基础虚基类的派生类如果没有实现基类的所有函数的话,本身还是虚拟类,但是上面的改进是可以的了
FingerStyle 2010-02-24
  • 打赏
  • 举报
回复
經理沒必要從接口繼承

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

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

個人觀點而已,可能跟你理解的不一樣
FingerStyle 2010-02-24
  • 打赏
  • 举报
回复
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(); //做事
這樣呢

你這個例子感覺有點..
InfidelX 2010-02-24
  • 打赏
  • 举报
回复
可以继承Iemployee,自己来写一个具体的employee,然后用这个指针指向具体的对象……
建议看看strategy模式,这个模式能帮解决根本问题~
redoffice 2010-02-24
  • 打赏
  • 举报
回复
不是那个意思。是这样的:


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();
}

Qlaiaqu 2010-02-24
  • 打赏
  • 举报
回复

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;
};


当然我不知道这上面的回答是否符合你的要求,如果不是,我建议你将你需要实现的结构贴出来,那样我们就可以为你分析并且改进你的结构,然后就可以符合你的工程了。
redoffice 2010-02-24
  • 打赏
  • 举报
回复
楼上能否说的具体点?比如弄个例子?
Qlaiaqu 2010-02-24
  • 打赏
  • 举报
回复
抽象类自然是不可以实例化的,但是可以引用抽象类的指针用来指向派生类对象。

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧