Head first design patterns Reading Notes-strategy)

Source: Internet
Author: User

Suppose your company has developed a duck simulation game, which can simulate various ducks, swim on the water, and make the sound of a cool, therefore, they sell well. This game was designed with the standard OO technology. An abstract Duck-based class has the Quack method that makes the sound of a cool and the Swim Method for swimming in the water, at the same time, it also has an abstract Display method. Every Duck sub-class (such as MallardDuck and RedheadDuck) overwrites it to make itself look different. For example:

Your company has many competitors. They are not vegetarian. Under increasing market pressure, your boss made a decision to improve the game and let the ducks in the game fly, if it succeeds, it will surely defeat everyone. Oh, this arduous task is handed over to you. You are a very good OO programmer, aren't you?

After receiving the task, you will start immediately. Isn't it easy? Add a Fly Method to the Duck base class so that all the Duck sub-classes can obtain this method and all the ducks can Fly. It's too simple. This is the power of OO.

The next day, you happily went to work at the company and handed over the modified program to the boss yesterday. After reading it, he would say, this kid is doing things well. While you are still imagining how the boss will praise you, the phone rang and the boss called: "I am on the board of directors and I just demonstrated your program, the duck can fly, but how can I see a duck flying? Are you kidding me? Be careful, don't let me fire you !" It was really scary. I felt a little calm and thought about it carefully. It was really not considerate. Not all ducks can Fly, but put the Fly method in the base class, then all types of ducks can Fly. What should I do?

You think about another method. In the subclass of the Rubber Duck, rewrite the Fly method so that it does nothing! After a while, you thought, "What should I do if I want to add a wooden bait duck? They cannot be called or fly ." Yes. What should I do? Rewrite the Fly and Quack methods? One or two are good. If there are dozens or hundreds of them, rewrite them one by one? It's terrible. The new mood suddenly becomes bad.

You realize that it is impossible to put the Fly and Quack methods in the base class, and then achieve the desired effect of the boss through inheritance. You need a clear solution. At this moment, you suddenly slapped your head. How is the interface used?

Interface

Extract the Fly method from the Duck base class and put it in an interface named IFlyable. Similarly, the Quack method is also extracted and put into the IQuackable interface. In this way, only the Duck sub-classes that require flight actions can implement the IFlyable interface, and the Duck sub-classes that can make sounds can implement the IQuackable interface. For example, RubberDuck cannot fly, so it does not implement the IFlyable interface, but it can make a squeak, so it must implement the IQuackable interface. For example, DecoyDuck cannot fly or call it, therefore, it only needs to inherit from the Duck base class. The UML diagram is as follows:

This method seems to have solved the problem, but think about it again. Is it true?

Since the C # interface only allows the declaration of the member signature, and does not allow any code implementation, each subclass that implements the IFlyable interface must provide its own Fly method implementation, this results in a large number of repeated code. Imagine if there are a total of 48 sub-classes in the program that implement the IFlyable interface, but one day the boss said, "We need to change the implementation of the Fly method (for example, the duck can Fly more quickly) ", what do you do? Change all the 48 subclass one by one? God, this is unimaginable. This method can only be said to bring you from one nightmare to another without solving the problem.

The truth is that user needs change every day (Do you know what they want ?), If we can minimize the number of program changes caused by changes in user needs, we need to do a lot of work, we can spend more time on things we are interested in (kicking and playing games), instead of working overtime under the boss's eyes after work.

What should I do? Here we will refer to a principle, which is the essence of almost all design patterns, that is:

Extract the changed parts and encapsulate them.

In short, it is to separate the code that is expected to change and put it together separately, so that we can easily modify it without affecting the existing code.

Let's take a look. What should we do in this situation?

Programming on interfaces rather than on implementation

First, analyze the cause of the trouble. The boss needs to make some changes to the program. Here, there are two methods: Fly and quack. The two methods require many different implementations and may be added, modified, or deleted in the future. In accordance with the above principles, we should extract the changed code of this branch, separate it from the duck base class. In this way, subsequent changes to this part of the code will not affect the duck class. If the problem is clear, you can solve it quickly!

And so on. You also need to know about polymorphism.

Brief Introduction to polymorphism.

What is polymorphism? Polymorphism refers to providing different implementation capabilities for methods with the same name, so that we do not need to care about the specific implementation of the method but rely solely on its name for calling operations.

What can we do through polymorphism? Polymorphism is very useful! To sum up, we can make the code clearer and more concise through it. For details, let's take a look at Allen's article "are you muttered today?"

Well, what a good oo programmer you are, polymorphism should be well known. Let's take a look at how polymorphism can be used to solve this problem.

Extract the changed part: extract the fly method and put it into the iflybehavior interface. Different fly behavior classes (child types) implement this interface, such as flywithwings and flynoway. Similarly, the quack extraction method is put into the iquackbehavior interface. Different quack behavior classes implement this interface, such as quacks, Squeak, and mutequack. For example:

If you want to dynamically set the behavior of the duck subclass at runtime, you can also add two set methods: setflybehavior and setquackbehavior to change the values of the flybehavior and quackbehavior variables. In this way, a bait duck can shake itself and become a red-headed duck.

Below is the Duck base class code:

Using System;

Namespace DesignPatterns
{
Public abstract class Duck
{
Protected IFlybehavior flybehavior;
Protected IQuackbehavior quackbehavior;

Public void Swim ()
{
Console. WriteLine ("Swim ");
}

Public void initialize mfly ()
{
This. flybehavior. Fly ();
}

Public void initialize mquack ()
{
This. quackbehavior. Quack ();
}

Public abstract void Display ();
}
}

The code of the redheadduck subclass is as follows:

Using System;

Namespace DesignPatterns
{
Public class RedheadDuck: Duck
{
Public RedheadDuck ()
{
// Braised duck can fly
This. flyable = new FlyWithWings ();
// The braised duck can be called
This. quackable = new Quack ();
}

Public override void Display ()
{
Console. WriteLine ("I'm a RedheadDuck ");
}
}
}

The final UML diagram is as follows:

Well, after this, the Code stability has been improved unprecedentedly. In the future, if you need to add more interesting behaviors, such as flying with a rocket, what should you do? You only need to create a class called flywithrocket to implement the iflybehavior interface and define your own implementation in the fly method without modifying the existing code. This is amazing! In the future, your work will be easier.

Well, let's look at it from another angle and think of a series of duck behaviors as a series of algorithms, such as employee salary calculation algorithms and menu rendering algorithms. We encapsulate these algorithms so that other classes can call different algorithms to calculate the final result. If the algorithm changes, you only need to modify the classes that contain the algorithm, instead of modifying the classes that use the algorithm.

Finally, the definition of policy mode is introduced: for a group of algorithms, each algorithm is encapsulated into an independent class with a common interface, so that they can be replaced with each other, it allows algorithms to change without affecting the client.

Download Code

Download Doc

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.