【问题标题】:Does pure composition break OOP concepts?纯组合会破坏 OOP 概念吗?
【发布时间】:2011-01-09 15:30:57
【问题描述】:
class Room{
  public:
    void ColorRoom(){};
};

class House{
  public:
    Room* GetRoom(){return &m_room;}
  private:
    Room m_room;
};

1) 没有房子,房间就不能存在,房子“有”房间。 (作曲)
2)另一种为房间着色的方法是在 House 中有一个方法,该方法将调用 ColorRoom in Room 方法,但这更多的是委托。 (我想避免这种情况)

我看到的唯一方法是上面的方法,但看起来返回对私有成员的引用正在破坏 OOP。这是个好设计吗?

【问题讨论】:

  • 是的。查看“Universe Types”以了解此问题的一个建议解决方案。

标签: oop composition


【解决方案1】:

问题是您没有明确公开您的私人成员。您的 API 只显示了获取房间的方法,而消费者不知道 House 是否正在创建该房间、返回私有字段中的内容或从 Web 服务获取房间。这是可靠的 OO。

【讨论】:

  • 这非常重要,但请注意,允许外部力量在未经验证的情况下修改您的对象状态通常是糟糕的设计。
【解决方案2】:

总的来说,你很好,因为House 自己创建了成员变量m_room——它不需要消费者在实例化后调用某些东西。这遵循了项目在实例化后立即可用的模式(它不需要像设置房间等特殊操作)。

我确实有一些小问题:

class Room
{
public:
    // virtual method to allow overriding
    virtual void ColorRoom(){};
};

class House
{
public:
    // Returning a non-const pointer in C++ is typically a bad smell.
    const Room& Room() const { return m_room; }
    // Allow for assignment and manipulating room, but breaks const-ness
    Room& Room() { return m_room; }
    // Facade method for houses with more than one room
    // You can forward parameters or come up with room-painting schemes, but you should
    // not require that a House has a Room called Room().
    virtual void ColorAllRooms()
    {
        m_room.ColorRoom();
    }
private:
    Room m_room;
};

【讨论】:

  • 请注意,virtual 指的是覆盖而不是重载
  • 你能在不继承的情况下覆盖一个函数吗?其次,如果用户希望修改房间,看起来他们需要调用 House 的方法,而后者又会调用 room 方法,类似于委托。
  • @Dario:噢!错字! @Frank:你不能在没有继承的情况下覆盖一个函数,因为覆盖的定义意味着继承。就委托而言,这就是想法 - 事物的集合可以将工作委托给其成员,这允许 House 的实际实现发生巨大变化,而无需修改消费者。
【解决方案3】:

我喜欢 NickLarsen 的回答,但我有一点要补充:

不要让对象的私有字段在该对象之外更改。如果您必须更改 Room 对象,请使用委托。也就是说,如果 Room 有一个 SetFloorColor(Color _color); 方法,那么你应该在 House 中调用

SetRoomFloorColor(Color _color){ m_room.SetFloorColor( _color ); }

【讨论】:

    【解决方案4】:

    手术发生在房间里,而不是房子里。如果您可以通过房屋返回对房间的不可变引用,然后可以对其进行操作,那么您并没有破坏 OOP。

    【讨论】:

      【解决方案5】:

      虽然我喜欢 NickLarsen 的回答,但我要指出另一件事:房间不会自行着色(或粉刷)。该动作通常由 Painter 完成,Painter 显然不是房间的成员。现在油漆工可以为整个房子着色,或者油漆工可以只在一个房间上工作。

      在这种情况下,我建议房间具有颜色属性,并且更改该颜色的行为由另一个对象在外部处理。

      这个想法表明 Color 属性必须是公共属性,并且您可以将要更改的房间的引用传递给 Painter 对象。

      【讨论】:

        【解决方案6】:

        公开私有成员会减少内聚并增加耦合。一般来说,你应该避免这样的代码:

        selection.getRecorder().getLocation().getTimeZone(); 
        

        这段代码维护性较差,违反了Law of Demeter

        【讨论】:

          猜你喜欢
          • 2018-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多