interface-oriented programming (II.)--programming example

Source: Internet
Author: User

Through the discussion of the previous article, I think my friends have a general understanding of "interface Programming". So in this article, we use an example to give you a visual impression of this important programming idea. In order to fully consider the beginner, so this example is very simple, I hope you master forgive me.

The question is raised

definition: Now we are going to develop an application that simulates the reading and writing of a mobile storage device, which is the data exchange between a computer and a USB stick, MP3, and a mobile hard disk.

context: known to implement a USB flash drive, MP3 player, mobile hard disk three kinds of mobile storage devices, require the computer to be able to exchange data with these three devices, and there may be new third-party mobile storage devices, so the computer must be scalable, The data can be exchanged with storage devices that are not currently known and may occur later. Each storage device between the implementation of read and write different, u disk and mobile hard disk only these two methods, Mp3player also has a Playmusic method.

noun definition: data exchange ={Read, write}

See the above question, I think you have a lot of ideas in mind, this is a very good solution to the problem, a lot of solutions can achieve results. Below, I cite a few typical scenarios.

List of solutions

Scenario One: define FlashDisk, Mp3player, mobileharddisk three classes, respectively, to implement the respective read and write methods. The above three classes are then instantiated in the computer class, and each class is read and written separately. For example, write Readfromflashdisk, Writetoflashdisk two methods for FlashDisk. A total of six methods.

Scenario Two: define abstract class Mobilestorage, write virtual methods in the inside read and write, three storage devices inherit this abstract class, and rewrite the read and write methods. The Computer class contains a member variable of type Mobilestorage and writes a get/set for it, so that only two methods are required in computer: ReadData and WriteData, and the different mobile devices are read and written by polymorphism.

Scenario Three: basically the same as scenario two, just do not define an abstract class, but rather define the interface Imobilestorage, the mobile memory class implements this interface. Polymorphism is achieved through dependency interface Imobilestorage in computer.

Scenario Four: define interfaces ireadable and iwritable, two interfaces contain only read and write, and then define interfaces Imobilestorage interfaces inherit from Ireadable and Iwritable, The rest of the implementation is the same as scenario three.

Below, let's analyze the above four scenarios:

First, the most straightforward scenario, the simplest to implement, but it has a fatal weakness: poor scalability. Or, it does not conform to the "open-close principle" (Note: It means opening the extension and closing the modification). When a third-party extended mobile storage device is in the future, the computer must be modified. This is like on a real computer, for each kind of mobile storage device to implement a different socket, and each has its own driver. When a new mobile storage device is available, we will have to remove the computer and add a new socket to write a driver for this new device. This design is obviously undesirable.

Another disadvantage of this scenario is that there is more redundant code. If there are 100 kinds of mobile storage, then we are not in the computer to write at least 200 methods, which is unacceptable!

Let us look again at Programme II and Programme III, where the two programmes have been discussed together because they are basically a programme (at the ideological level), except that the means of implementation are different, one using an abstract class, one using an interface, and the ultimate goal should be the same.

Let's start by evaluating this scenario: first it solves the problem of code redundancy, because the mobile device can be dynamically replaced, and all the common interfaces are implemented, so that regardless of the number of mobile devices, as long as a read method and a write method, polymorphism helps us solve the problem. For the first problem, because it can be dynamically replaced at runtime without having to hard code the mobile storage class in computer, a new third-party device can be replaced completely. This is called "dependency interface, rather than dependency with concrete class", do not believe you see, Computer class has only one mobilestorage type or imobilestorage type of member variable, as to what the specific type of this variable, it does not know, It depends on what we assign to the variable at run time. As a result, the coupling of the computer and the mobile memory class is greatly reduced.

So should we choose an abstract class or an interface? Remember the first article I suggested for abstract classes and interface selection? Look at the motive. Here, our motive is obviously to achieve polymorphism rather than for code reuse, so of course we use interfaces.

Finally, let's take a look at scenario four, which is similar to scenario three, except that the "readable" and "writable" two rules are abstracted into interfaces respectively, and then let Imobilestorage inherit them. In doing so, it is clear that the flexibility is further improved, but is there any suspicion of excessive design? My point is: it depends on the situation. This is also possible if classes are available in our application that only implement read methods or only write methods, such as CD-ROM. If we know that everything that comes up in the future is readable and can be written, then these two interfaces are not necessary. In fact, if you leave the Write method of a read-only device empty or throw an exception, you can also avoid these two interfaces. In a word: The theory is dead, people are living, everything from the reality needs to prevent the design of inadequate, but also to prevent excessive design.

In this case, we would think that the future of mobile storage is readable and can be written, so we choose scenario three.

Realize

Below, we want to implement the solution. The language I chose is C #, but it doesn't use the unique nature of C # in code, so you can refer to friends in other languages as well.

First write the Imobilestorage interface:

Code:imobilestorage

namespace interfaceexample{    publicinterface  imobilestorage    {        void Read (); // Read Data        from itself void Write (); // write data to itself    }

The code is simple, there are only two methods, nothing to say, next is the implementation code of three mobile storage devices:

U disk

Code:flashdisk

namespaceInterfaceexample { Public classFlashdisk:imobilestorage { Public voidRead () {Console.WriteLine ("Reading from FlashDisk ..."); Console.WriteLine ("Read finished!"); }         Public voidWrite () {Console.WriteLine ("Writing to FlashDisk ..."); Console.WriteLine ("Write finished!"); }    }}

MP3

Code:mp3player

namespaceInterfaceexample { Public classMp3player:imobilestorage { Public voidRead () {Console.WriteLine ("Reading from Mp3player ..."); Console.WriteLine ("Read finished!"); }         Public voidWrite () {Console.WriteLine ("Writing to Mp3player ..."); Console.WriteLine ("Write finished!"); }         Public voidPlaymusic () {Console.WriteLine ("Music is playing ..."); }    }}

Mobile HDD

Code:mobileharddisk

namespaceInterfaceexample { Public classMobileharddisk:imobilestorage { Public voidRead () {Console.WriteLine ("Reading from Mobileharddisk ..."); Console.WriteLine ("Read finished!"); }         Public voidWrite () {Console.WriteLine ("Writing to Mobileharddisk ..."); Console.WriteLine ("Write finished!"); }    }}

As you can see, they all implement the Imobilestorage interface and rewrite their different read and write methods. Below, let's write computer:

Code:computer

namespaceinterfaceexample{ Public classComputer {PrivateImobilestorage _usbdrive;  Publicimobilestorage usbdrive {Get            {                return  This. _usbdrive; }            Set            {                 This. _usbdrive =value; }        }         Publiccomputer () {} Publiccomputer (Imobilestorage usbdrive) { This. Usbdrive =usbdrive; }             Public voidReadData () { This. _usbdrive.read (); }         Public voidWriteData () { This. _usbdrive.write (); }    }}

The usbdrive is a removable storage device, the name is used to make people feel intuitive, as we normally use the computer USB jack Plug and unplug the device.

Ok! Let's test whether our "computer" and "Mobile storage devices" are working properly. I am using the C # console program, the specific code is as follows:

Code: Test Codes

namespaceinterfaceexample{classProgram {Static voidMain (string[] args) {Computer computer=Newcomputer (); Imobilestorage Mp3player=NewMp3player (); Imobilestorage FlashDisk=NewFlashDisk (); Imobilestorage Mobileharddisk=NewMobileharddisk (); Console.WriteLine ("I inserted my MP3 Player into my computer and copy some music to it:"); Computer. Usbdrive=Mp3player; Computer.            WriteData ();            Console.WriteLine (); Console.WriteLine ("Well,i also want to copy a great movie to my computer from a mobile hard disk:"); Computer. Usbdrive=Mobileharddisk; Computer.            ReadData ();            Console.WriteLine (); Console.WriteLine ("ok! I have to read some files from my flash disk and copy another file to it:"); Computer. Usbdrive=FlashDisk; Computer.            ReadData (); Computer.            WriteData ();        Console.ReadLine (); }    }}

Now compile, run the program, if there is no problem, you will see the following results:

Figure 2.1 test results for various mobile storage devices

Well, it seems that our system is working well.

Later......

Just after one weeks, someone sent a new mobile storage device newmobilestorage, let me test can use, I smiled, thought this is not a piece of cake, let us look at the power of interface-oriented programming! Modify the test program to read as follows:

Code: Test Codes

namespaceinterfaceexample{classProgram {Static voidMain (string[] args) {Computer computer=Newcomputer (); Imobilestorage Newmobilestorage=NewNewmobilestorage (); Console.WriteLine ("now,i AM Testing the new mobile storage:"); Computer. Usbdrive=Newmobilestorage; Computer.            ReadData (); Computer.            WriteData ();        Console.ReadLine (); }    }}

Compile, run, and see the results:

Haha, magic Bar, computer do not have to change, you can make new equipment normal operation. This is called "open to expansion, closed on modification".

Figure 2.2 New device expansion test results

A few days later, I was informed that there is a mobile device called SuperStorage to receive our computer, I thought to come, whether you are "super storage" or "Premium storage", my "interface-oriented programming Dafa" to get you all done.

However, when the equipment really sent, I was dumbfounded, the development of this new equipment team did not get our Imobilestorage interface, naturally did not comply with this agreement. The reading and writing methods of this device are not called Read and write, but are called Rd and WT, which is finished ... Does not meet the interface Ah, can't plug in. But, don't worry, let's go back to reality and find a way out. Let's think about it: if you have a USB port on your computer, and someone takes a PS/2 mouse to plug it in, what do you do? Remember, is there something called a "Ps/2-usb" converter? Also known as an adapter, you can convert different interfaces. That's right! There are also converters in the program.

Here, I'm going to introduce a design pattern called "Adapter". It acts as an adapter in the real world, connecting two plug-ins with inconsistent interfaces. Since this article is not about design mode, and adapter design mode is very well understood, so I will not be detailed, first look at my design of the class diagram it:
, although SuperStorage does not implement Imobilestorage, we define a superstorageadapter that implements Imobilestorage, which aggregates a superstorage, and to adapt Rd and WT to read and Write,superstorageadapter

Figure 2.3 Adapter mode application schematic

The specific code is as follows:

Code:superstorageadapter

namespaceinterfaceexample{ Public classSuperstorageadapter:imobilestorage {PrivateSuperStorage _superstorage;  Publicsuperstorage SuperStorage {Get            {                return  This. _superstorage; }            Set            {                 This. _superstorage =value; }        }             Public voidRead () { This. _SUPERSTORAGE.RD (); }         Public voidWrite () { This. _SUPERSTORAGE.WT (); }    }}

OK, now let's test the new device that we've adapted, and test the code as follows:

Code: Test Codes

namespaceinterfaceexample{classProgram {Static voidMain (string[] args) {Computer computer=Newcomputer (); Superstorageadapter Superstorageadapter=NewSuperstorageadapter (); SuperStorage SuperStorage=NewSuperStorage (); Superstorageadapter.superstorage=SuperStorage; Console.WriteLine ("now,i AM Testing the new super storage with adapter:"); Computer. Usbdrive=Superstorageadapter; Computer.            ReadData (); Computer.            WriteData ();        Console.ReadLine (); }    }}

The following results will be obtained when running:

Figure 2.4 Running new device test results with adapter mode

Ok! Although there are some difficulties, but with the help of design mode, we have realized the operation of the new device without modifying computer any code.

Well, the theory is more than enough in the first one, so I'm not going to say much here. I hope you will combine the first theory and this example to think carefully about interface-oriented issues. Of course, don't forget to combine reality.

In the next article, I will analyze the concept of interface-oriented programming in the classic design pattern. NET platform in the hierarchical architecture of the use of interfaces.

interface-oriented programming (II.)--programming example

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.