面向对象的设计建议

poc*_*coa 15 c++ oop visibility class-members

这是我的代码:

class Soldier {
public:
   Soldier(const string &name, const Gun &gun);
   string getName();
private:
   Gun gun;
   string name;
};

class Gun {
public:
   void fire();
   void load(int bullets);
   int getBullets();
private:
   int bullets;
}
Run Code Online (Sandbox Code Playgroud)

我需要调用Gun的所有成员函数而不是Soldier对象.就像是:

soldier.gun.fire();
Run Code Online (Sandbox Code Playgroud)

要么

soldier.getGun().load(15);
Run Code Online (Sandbox Code Playgroud)

那么哪一个是更好的设计?将枪对象隐藏为私有成员并使用getGun()函数访问它.或者让它成为公共会员?或者我可以封装所有这些函数会使实现更难:

soldier.loadGun(15); // calls Gun.load()
soldier.fire(); // calls Gun.fire()
Run Code Online (Sandbox Code Playgroud)

那么你觉得哪一个最好?

Fru*_*ner 21

我想说你的第二个选择:

soldier.loadGun(15); // calls Gun.load()
soldier.fire(); // calls Gun.fire()
Run Code Online (Sandbox Code Playgroud)

最初它是更多的工作,但随着系统变得越来越复杂,你可能会发现一名士兵想要在开枪之前和之后做其他事情(也许检查他们是否有足够的弹药然后尖叫"模具吸盘!!"然后开火,然后嘀咕"那就是受伤了",并检查一下他们是否需要重装.它还从士兵类的用户那里隐藏了枪的准确性的不必要细节.

  • 您对士兵类的描述为+1:P (3认同)
  • 另外,不要说loadGun,说prepareWeapon.这样,当你的士兵在坦克中时,当他应该旋转坦克炮时,他并没有用手枪摸索. (2认同)

Aus*_*nen 11

首先,你要通过从课堂外访问来违反Demeter法.GunSoldier

我会考虑这样的方法:

soldier.ArmWeapon(...);
soldier.Attack(...);
Run Code Online (Sandbox Code Playgroud)

这样你也可以实现你的拳头,刀,手榴弹,棒球棒,激光猫等.


bry*_*ker 7

德米特定律会说要封装这些功能.

http://en.wikipedia.org/wiki/Law_of_Demeter

这样,如果你想在士兵和枪之间进行某种类型的交互,你就有了插入代码的空间.

编辑:发现从维基百科的链接相关文章: http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf 报童的例子是非常,非常相似你发布的士兵例子.

  • 请记住,避免陷入"低点计数法"(http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx) (3认同)

Mat*_*son 5

实际上,这取决于你想要拥有多少控制权.

为了模拟真实世界,您甚至可能想要完全封装枪对象,并且只需要一个soldier.attack()方法.士兵.攻击()方法然后会看到士兵是否携带枪,以及枪的状态是什么,并在必要时开火或重新加载.如果两种操作都没有足够的弹药,或者可能将枪射向目标并逃跑