Original article. Please indicate the source for reprinting. Thank you!
Author: Qinglin, blog name: feikong jingdu
We know that the C ++ polymorphism can provide the same interface for different implementations, And the adapter mode can also make the same interface different implementations. Here is an example to illustrate these two things :)
Suppose I want to design a set of classes to operate on disk partitions. This class has three interfaces, which are used to open a disk, read a disk, write a disk, and close an opened disk. Here, we can encapsulate the system's functions for disk read and write.
In Linux or UNIX, these functions are: open, read, write, and close.
In Windows, these functions are createfile, readfile, writefile, and closehandle.
When reading and writing data to a disk, these two sets of APIs are very different. One big difference is that in windows, these functions operate on the disk in slices.
Now, we will design this class using the polymorphism method. The following is the pseudocode of these classes:
Class device_io <br/>{< br/> Public: <br/> device_io (): handle (null) {}; <br/> virtual ~ Device_io () <br/>{< br/> If (handle) <br/> device_close (* handle); <br/> Delete handle; <br/>}< br/> virtual int device_open (...) = 0; <br/> virtual int device_read (...) = 0; <br/> virtual int device_write (...) = 0; <br/> virtual int device_close (...) = 0; </P> <p> protected: <br/>/* Data */<br/> void * handle; <br/> }; <br/> class linux_io: Public device_io <br/>{< br/> Public: <br/> int device_open (...) <br/> {<br/> ...... <br/> handle = new int; <br/> * handle = open (devname ,...); <br/> ...... <br/>}< br/> int device_read (...) <br/> {<br/> ...... <br/> Read (* handle ,...); <br/> ...... <br/>}< br/> int device_write (...) <br/> {<br/> ...... <br/> write (* handle ,...); <br/> ...... <br/>}< br/> int device_close (...) <br/> {<br/> ...... <br/> close (* handle); <br/> ...... <br/>}< br/> PRIVATE: <br/>/* Data */<br/>}; <br/> class win32_io: public device_io <br/>{< br/> Public: <br/> int device_open (...) <br/> {<br/> ...... <br/> handle = new handle; <br/> * handle = createfile (...); <br/> ...... <br/>}< br/> int device_read (...) <br/> {<br/> ...... <br/> readfile (* handle ,...); <br/> ...... <br/>}< br/> int device_write (...) <br/> {<br/> ...... <br/> writefile (* handle ,...); <br/> ...... <br/>}< br/> int device_close (...) <br/> {<br/> ...... <br/> closehandle (* handle); <br/> ...... <br/>}< br/> PRIVATE: <br/>/* Data */<br/> };
If you want to use it, it may be like this:
Int main (INT argc, const char * argv []) <br/>{< br/>... <br/> device_io * pdev = NULL; <br/> # ifdef Win32 <br/> pdev = new win32_io (...); <br/> # else <br/> pdev = new linux_io (...); <br/> # endif </P> <p> pdev-> Read (...); <br/>... <br/> return 0; <br/>}
The above is the use of C ++ polymorphism to achieve Io operations on different platforms.
However, if I have completed a project under Linux, and I do not want to change the code and port it to wndows, how can we change the above Code.
The following uses the adapter mode:
Now we have this operation class in Linux:
Class linux_io <br/>{< br/> Public: <br/> linux_io (): FD (-1) {}< br/> ~ Linux_io () <br/>{< br/> linux_close (FD); <br/>}< br/> int device_open (...); <br/> int device_read (...); <br/> int device_write (...); <br/> int device_close (...); <br/> PRIVATE: <br/> int FD; <br/>/* Data */<br/> };
Therefore, we also design a similar Io class for wndows:
Class win32_io <br/>{< br/> Public: <br/> win32_io (): handle (invalid_handle_value); <br/> virtual ~ Win32_io (); </P> <p> int device_open (...); <br/> int device_read (...); <br/> int device_write (...); <br/> int device_close (...); <br/> PRIVATE: <br/>/* Data */<br/> handle; <br/> };
And define the corresponding adapter class:
Class win32_io_adapt: Public linux_io <br/>{< br/> Public: <br/> win32_io_adapt (win32_io * pwin_io): _ pwin32_io (pwin_io) {}</P> <p> int device_open (...) <br/>{< br/>... <br/> _ pwin32_io-> device_open (...); <br/>... <br/>}< br/> int device_read (...) <br/>{< br/>... <br/> _ pwin32_io-> device_read (...); <br/>... <br/>}< br/> int device_write (...) <br/>{< br/>... <br/> _ pwin32_io-> device_write (...); <br/>... <br/>}< br/> int device_close (...) <br/>{< br/>... <br/> _ pwin32_io-> device_close (...); <br/>}< br/> PRIVATE: <br/>/* Data */<br/> win32_io * _ pwin32_io; <br/> };
In this way, we can use
Int main (INT argc, const char * argv []) <br/>{< br/>... <br/> device_io * pdev = NULL; <br/> # ifdef Win32 <br/> win32_io * pwin32 = new win32_io (...); <br/> win32_io_adapt * pwin32_adapt = new win32_io_adapt (pwin32); <br/> pdev = pwin32_adapt; <br/> # else <br/> pdev = new linux_io (...); <br/> # endif </P> <p> pdev-> Read (...); <br/>... <br/> return 0; <br/>}
The adapter mode encapsulates all functions without changing the code for unified use.