Re: How to hide implementation details?
On 26 mai, 04:33, Immortal Nephi <Immortal_Ne...@hotmail.com> wrote:
I want to create an interface of a door. The client is=
able to see
the implementation behind the interface because inheritance is
present. The code is stored in the header. How do I hide the
implementation?
I assume you mean that a specific implementation of the interface is
exposed.
You could look into creational patterns. For C++ there is the
compilation firewall idiom that allows you to expose an implementation
but hide the nitty gritty.
A door is an abstraction of a particular arrangement of a=
rectangular
piece of material with hinges and a doorknob. It has four routines of
Open(), Close(), isOpened(), and isClosed().
It could also be ajar :)
And the doorknob is in turn an abstraction of a particula=
r formation
of brass, nickel, iron, or steel. It has four routine of Lock(),
Unlock(), IsLocked(), and IsUnlocked().
And also, Color_Knob is in turn an abstraction of some co=
lors.
How do I put three objects of Door, Knob, and Color_Knob =
together
into a function or another class. Is it the way how design looks
good?
[snip]
Redecomposing your design you have two abstraction:
- a Door (which could be a specific Gate abstraction) which handle a
state (opened/closed) and cab be operated (open/close). But
eventually, the closing or opening could fail. Keeping as close as
possible to your design, I could write it (with robust interface not
failing if by example I try to open door already opened):
class Door
{
public:
Door(bool is_open = false):m_is_open{}
virtual ~Door() {}
// return true upon success
bool Open()
{if(!m_is_open)m_is_open = tryOpenDoor();
return m_is_open; }
// return true upon success
bool Close()
{if(m_is_open)m_is_open = !tryCloseDoor();
return !m_is_open; }
bool IsOpened() const{ return m_is_open; }
protected: // real door implement opening/closing condition
// return true upon success
// pre Door is closed
virtual bool tryOpenDoor()=0;
// return true upon success
// pre Door is opened
virtual bool tryCloseDoor()=0;
private:
bool m_is_open;
};
Now, as others pointed out, for normal people a knob is not a door.
And it doesn't necessarily have a state. The only thing you know is
that is you want to open with it, it can grant you or not to open the
door. Lets keep it simple:
struct Knob
{
virtual ~Knob(){}
// return true upon success
virtual bool tryOpenWithKnob()=0;
// return true upon success
virtual bool tryCloseWithKnob()=0;
};
Now You can have a Knob with a Lock:
class KnobWithLock: public Knob
{
public:
KnobWithLock(bool is_locked)
: Knob()
, m_is_locked(is_locked){}
bool Lock()
{ m_is_locked = true; // easy lock
return m_is_locked;}
bool Unlock()
{ m_is_locked = false; // easy unlock
return m_is_locked;}
bool IsLocked () { return m_is_locked; }
virtual bool tryOpenWithKnob()
{ /* can open only if unlocked */
return !m_is_locked; }
virtual bool tryCloseWithKnob()
{ /* can always close */
return true; }
private:
bool m_is_locked;
};
Now if you want to make a door with a knob:
class DoorWithKnob: public Door
{
public:
DoorWithKnob(Knob* knob = NULL):m_knob(knob){}
Knob* knob()const{return m_knob;}
protected:
virtual bool tryOpenDoor()
{ // can open if no knob
return m_knob ? m_knob->tryOpenWithKnob() : true;
}
virtual bool tryCloseDoor()=0;
{ // can close if no knob
return m_knob ? m_knob->tryCloseWithKnob() : true;
}
private:
Knob* m_knob;
};
Now, concerning the colored knob. The color is in fact an attribute of
a Knob that doesn't modify it. You could use a kind of decoration:
template<class TKnobType>
class ColoredKnob: TKnobType
{
// ... code to handle color of knob
};
And you main program is:
int main()
{
ColoredKnob<KnobWithLock> knob;
DoorWithKnob door(&knob);
knob.Select_Brass();
knob.Unlock();
door.Open();
knob.Lock();
door.Close();
return 0;
}
--
Michael