Date post: | 25-May-2015 |
Category: |
Documents |
Upload: | somenath-mukhopadhyay |
View: | 363 times |
Download: | 1 times |
Purpose
To decouple abstraction from implementation so that the two can be extended/reused independently
Class Diagram
Applicability
Helps us in avoiding a permanent binding between an abstraction and implementation
It might be useful if we want to select/switch the implementation at runtime
Abstraction and implementation can be extended independently. Different abstraction can be attached to different implementation
Applicability
The client cannot know anything about the implementation. Hence if the implementation is changed, the client code will not be recompiled
Example
We have two classes – Window and WindowImp
Window class has got two subclasses – IconWindow and TransientWindow
WindowImp class has got two subclasses – XwindowImp and PMWindowImp
Example
Window class realizes its functionalities through the functions of WindowImp class
Example - Window.hclass Window{public:
Window();
WindowImp* GetWindowImp(const int type_of_implementation );
void DrawRect(const Coord& aTopLeft, const Coord& aBottomRight);
void DrawLine(const Coord& aBegin, const Coord& aEnd);
private:WindowImp* imp;
};
class IconWindow : public Window{public:
IconWindow();void DrawBorder(const Coord& aTopLeft, const Coord& aBottomRight);
};
class TransientWindow : public Window{public:
TransientWindow();};
Explanation – Window classIt has got the basic functionalities like DrawRect and DrawLine
It has got GetWindowImp to bind a specific Window to another specific implementation
The IconWindow class has its own function DrawBorder which is implemented through the Window class functions
TransientWindow class just uses Window class functions
WindowImp classclass WindowImp{public:
WindowImp();virtual void DeviceLine(const Coord& aBeginningPoint, const Coord& aEndPoint) = 0;virtual void DeviceRect(const Coord& aTopLeft, const Coord& aBottomRight) = 0;
};
class XWindowImp : public WindowImp{public:
XWindowImp();virtual void DeviceLine(const Coord& aBeginningPoint, const Coord& aEndPoint);virtual void DeviceRect(const Coord& aTopLeft, const Coord& aBottomRight);
};
class PMWindowImp : public WindowImp{public:
PMWindowImp();virtual void DeviceLine(const Coord& aBeginningPoint, const Coord& aEndPoint);virtual void DeviceRect(const Coord& aTopLeft, const Coord& aBottomRight);
};
Explanation – WindowImp class
Its an abstract class having two pure virtual functions
Two subclasses have been derived from it – XWindowImp and PMWindowImp
These two subclasses override the base class functions according to the specific needs
WindowImp class
WindowImp::WindowImp() {}
XWindowImp::XWindowImp(){}
PMWindowImp::PMWindowImp() {}
void XWindowImp::DeviceLine(const Coord& aBeginningPoint, const Coord& aEndPoint){
cout<<"Draw the XWindow version of Line draw"<<endl;}
void XWindowImp::DeviceRect(const Coord &aTopLeft, const Coord &aBottomRight){
cout<<"Draw the XWindow version of Rectangle draw"<<endl;}
void PMWindowImp::DeviceLine(const Coord &aBeginningPoint, const Coord &aEndPoint){
cout<<"Draw the PMWindow version of Line draw"<<endl;}
void PMWindowImp::DeviceRect(const Coord &aTopLeft, const Coord &aBottomRight){
cout<<"Draw the PMWindow version of Rectangle draw"<<endl;
}
Window classWindow::Window(){
imp = 0;}
WindowImp* Window::GetWindowImp(const int type_of_implementation){
imp = WindowSystemFactory::Instance()-> MakeWindowImp(type_of_implementation);return imp;
}
void Window::DrawLine(const Coord& aBegin, const Coord& aEnd){
imp->DeviceLine(aBegin, aEnd);}
void Window::DrawRect(const Coord &aTopLeft, const Coord &aBottomRight){
imp->DeviceRect(aTopLeft,aBottomRight);}
IconWindow::IconWindow() {}
void IconWindow::DrawBorder(const Coord& aTopLeft, const Coord& aBottomRight){
DrawRect(aTopLeft, aBottomRight);}
TransientWindow::TransientWindow() {}
Window class
It creates the specific implementation class through the factory class WindowSystemFactory
WindowSystemFactory Class
class WindowImp;
class WindowSystemFactory{public:
static WindowSystemFactory* Instance();WindowImp* MakeWindowImp(const int type_of_implementation );
private:WindowSystemFactory();static WindowSystemFactory* instance;
};
WindowSystemFactory classWindowSystemFactory* WindowSystemFactory::instance = 0;
WindowSystemFactory::WindowSystemFactory() {}
WindowSystemFactory* WindowSystemFactory::Instance(){
if (NULL = = instance){
instance = new WindowSystemFactory;}
return instance;}
WindowImp* WindowSystemFactory::MakeWindowImp(const int type_of_implementation){
if (type_of_implementation == XwindowImplementation)
return new XwindowImp;
if (type_of_implementation == PMWindowImplementation)
return new PMWindowImp;
return 0;}
Client of Abstraction
IconWindow* XIconWindow = new IconWindow;
XIconWindow->GetWindowImp(XWindowImplementation);
const Coord pt0(1,2);const Coord pt1(7,8);
XIconWindow->DrawBorder(pt0,pt1);
TransientWindow* PMTransientWindow = new TransientWindow;
PMTransientWindow->GetWindowImp(PMWindowImplementation);
PMTransientWindow->DrawRect(pt0,pt1);
IconWindow* PMIconWindow = new IconWindow;
PMIconWindow->GetWindowImp(PMWindowImplementation);
PMIconWindow->DrawLine(pt0,pt1);}
Explanation
There are two Window objects – XIconWindow and PMTransientWindow
As the name suggests XiconWindow will create an IconWindow object and it will attach itself to an XWindowImp implementation
On the other hand PMTransientWindow will create a TransientWindow object and attach itself to an PMWindowImp implementation
Explanation
The attachment of an Window object to a specific Implementation is done through GetWindowImp function
This function takes the help of the WindowSystemFactory class to create specific implementation
Explanation
Similarly we can have one IconWindow object and attach it to a PMWindowImp implementation or a TransientWindow object and attach it to a XwindowImp implementation
contd...
If there is only one implementation, there is no need to create an abstract Implementor class.
This is only one-to-one relationship between the abstraction and its implementation
However, it helps us in avoiding the recompilation of the client code when the implementation class is changed
contd...
In the example, we have attached an abstraction to its implementation by taking the help of the WindowSystemFactory class
This can also be achieved in the constructor of the Window class. For example the window class can instantiate the specific implementation depending on the parameter passed to its constructor