2010-01-26 17 views
6
class Room{ 
    public: 
    void ColorRoom(){}; 
}; 

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

1) Pokój nie może istnieć bez domu, dom "ma" pokój. (skład)
2) Innym sposobem na kolorowanie pokoju byłoby posiadanie w House metody, która wywołałaby metodę ColorRoom in Room, ale jest to bardziej delegacja. (chcę tego uniknąć)

Jedyny sposób, jaki widzę, to ten powyżej, ale wygląda na to, że powracający odnośnik do prywatnego członka łamie OOP. Czy to dobry projekt?Czy czysta kompozycja łamie koncepcje OOP?

Odpowiedz

4

Ogólnie rzecz biorąc, jesteś dobry, ponieważ House sam tworzy zmienną składową m_room - nie wymaga ona od konsumenta wywoływania czegoś po utworzeniu instancji. Wynika to z tego, że dany przedmiot może być użyty natychmiast po utworzeniu (nie wymaga specjalnych działań, takich jak ustawienie pokoju czy cokolwiek innego).

mam kilka drobnych szkodliwym prowizje:

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

To działa dobrze, a po krótkim objaśnieniu zobacz moją odpowiedź. –

+0

Należy zauważyć, że "wirtualny" odnosi się do * przesłaniania *, a nie * przeciążania *. – Dario

+0

Czy można zastąpić funkcję bez dziedziczenia? Po drugie, jeśli użytkownik chce zmodyfikować pokój, wygląda na to, że musi wywołać metodę House, która z kolei wywoła metodę room, podobnie jak delegacja. –

2

Operacja się dzieje na sali, a nie dom. Jeśli możesz zwrócić niezmienne odniesienie do pokoju przez dom, w którym można następnie operować, nie łamiesz OOP.

5

Chodzi o to, że nie ujawniasz bezpośrednio swojego prywatnego członka. Twój interfejs API pokazuje tylko metodę zdobycia pokoju, a konsument nie wie, czy House tworzy ten pokój, zwraca coś przechowywanego w prywatnym polu lub uzyskuje pokój z usługi sieciowej. To solidne OO.

+2

Jest to bardzo istotne, ale proszę zauważyć, że zazwyczaj jest to zły projekt, który pozwala siłom zewnętrznym modyfikować stan obiektu bez sprawdzania poprawności. –

4

Lubię odpowiedź NickLarsen, ale mam jedną rzecz do dodania:

nie pozwól prywatne pole obiektu zostać zmieniona poza tym obiekcie. Jeśli musisz zmienić delegowanie uprawnień do obiektu na Room. To jest, jeśli Room ma metodę SetFloorColor(Color _color); następnie należy umieścić w House wezwanie do

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

Chociaż lubię odpowiedź NickLarsen za, chciałbym podkreślić jedną rzecz: pokoje nie kolor (lub farby) sami. Ta czynność jest zwykle wykonywana przez Paintera, który oczywiście nie jest członkiem pokoju. Teraz malarz mógłby pokolorować cały dom lub malarz mógł pracować tylko w jednym pokoju.

Proponuję w tym przypadku, aby pokój miał właściwość koloru, a zmiana koloru jest obsługiwana zewnętrznie przez inny obiekt.

Pomysł ten sugerowałby, że właściwość Kolor musi być własnością publiczną oraz że można przekazać odniesienie do pomieszczenia, które zostanie zmienione na obiekt Painter.

0

Ujawnienie prywatnych członków zmniejsza spójność i zwiększa sprzężenie. Generalnie, należy uniemożliwić kodu tak:

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

Kod ten jest mniejszy w utrzymaniu i narusza Law of Demeter.