Разве чистая композиция нарушает концепции ООП? - PullRequest
6 голосов
/ 26 января 2010
class Room{
  public:
    void ColorRoom(){};
};

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

1) Комната не может существовать без дома, дом "имеет" комнату.(состав)
2) Другой способ раскрасить комнату - это иметь метод в House, который будет вызывать метод ColorRoom in Room, но это скорее делегирование.(я хочу избежать этого)

Единственный способ, который я вижу, - это приведенный выше, но похоже, что возвращение ссылки на приватный член нарушает ООП.Это хороший дизайн?

Ответы [ 6 ]

5 голосов
/ 26 января 2010

Дело в том, что вы явно не разоблачаете своего частного участника. Ваш API просто показывает метод получения комнаты, а потребитель не знает, создает ли Хаус эту комнату, возвращает что-то, хранящееся в приватном поле, или получает комнату от веб-службы. Это твердое OO.

4 голосов
/ 26 января 2010

Мне нравится ответ Ника Ларсена, но мне нужно добавить одну вещь:

Не позволяйте частному полю объекта изменяться вне этого объекта. Если вам нужно изменить объект Room, используйте делегирование. То есть, если Room имеет метод SetFloorColor(Color _color);, то вам нужно House вызвать

SetRoomFloorColor(Color _color){ m_room.SetFloorColor( _color ); }
4 голосов
/ 26 января 2010

В целом, вы хороши, поскольку 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;
};
2 голосов
/ 26 января 2010

Хотя мне нравится ответ Ника Ларсена, я хотел бы отметить еще одну вещь: комнаты сами не красят (или красят). Это действие обычно выполняется художником, который явно не является членом комнаты. Теперь художник мог покрасить весь дом, или художник мог работать только в одной комнате.

В этом случае я бы предположил, что в комнате есть свойство цвета, а действие по изменению этого цвета обрабатывается внешним объектом другим объектом.

Эта идея предполагает, что свойство Color должно быть общедоступным и что вы передадите ссылку на комнату, которая будет изменена на объект Painter.

2 голосов
/ 26 января 2010

Операция происходит в комнате, а не в доме. Если вы можете вернуть неизменную ссылку на комнату через дом, которой затем можно будет управлять, вы не нарушите ООП.

0 голосов
/ 27 января 2010

Разоблачение частных членов уменьшает сцепление и увеличивает сцепление. Как правило, вы должны запретить такой код:

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

Этот код менее понятен и нарушает Закон Деметры .

...