This blog is from the real life, refined out of the design concept, it is now skeleton, now I have to code examples, complete the process of flesh and blood, in order to let everyone living experience of the essence of design.
Since we have been learning object-oriented programming, it has facilitated our thinking mode, a thing with what, in the corresponding attributes and methods combined.
(▽) There is nothing difficult, but you learn the most basic grammar and even oneself are not very understanding of the language, with a C language program, you can easily change it into C#,java and so on, what is the difficulty? Most programmers distort the C # language, porting C's syntax to C # (when I don't know C #, I do it myself), it's not scary, it's terrible, it's not going to change.
Language is a tool that learns to be understood, but different design ideas determine the essential difference of language.
To get to the point, take a step-by-step analysis of a simple duck game program.
First design a Duck object, isn't it? Roughly like this:
Copy Code code as follows:
public class Duck
{
void Quack () {
//... Ducks will bark.
}
void Swim () {
//... Can swim
}
void Display () {
//... Appearance
}
}
Then ducks in the game have a variety of ducks swimming in a paddle, while sipping, all kinds of ducks inherit duck class Oh, the game in the expected operation.
Is this supposed to be standard OO (Object oriented) technology? The game is running perfectly ...
At present ducks can call can swim, all in the water how boring? Make it a creative one:
Ugly duckling can also fly to the sky?? O (∩_∩) o
Now you want the Ducks to fly, you have to add a flying method to the Ducks, like this:
Copy Code code as follows:
public class Duck
{
void Quack () {
//... Ducks will bark.
}
void Swim () {
//... Can swim
}
void Display () {
//... Appearance
}
void Fly () {
//... Flight
}
}
Method has been added, the game of small ducks can fly slightly.
Now the question is just appearing:
In the demo program, "Rubber Duck" flying on the screen, the game has a variety of ducks.
When there is no fly (), small ducks can run smoothly. adding Fyl () to the parent class causes all subclasses to have fly (), even those that cannot be dispensed with, so:
Local changes to the code, the impact level is not only partial.
If you look at this picture, it might coincide with your idea:
Cover off the "Rubber duck" way of flying. This is a good choice, so, "rubber duck" will not fly everywhere ~ ~ (Note oh "rubber duck" will be called-"squeak").
The game now joins a kind of duck ~ the question comes again ~ ~
Now join the member is-"Bait duck" (decoyduck) it is a wooden fake duck, it can not fly of course will not be called ~
OK, now for this new member, just do it:
Continue to cover it in a way that it only honestly swims in the water!
When do you think this tedious work is going to start? Duck species Unlimited, your nightmare infinite ~ Inherit this solution, it seems decisive not ah, to change to change.
What do you think of this design:
I define some interfaces, and now do two first, one flyable, one quackable:
The Duck class is also changed, containing only two methods: Swim (), Display ():
Then let the different subclasses to inherit the Duck class, respectively, realize fly () and quack (), interface also used, how do you think?
It seems to be a bit of a use, but, for another big angle, subclass inherits the implementation of those fly (), quack () is a bit of repetitive code, however, duplicate code is acceptable, but, in your maintenance, if there are 30 duck subclasses, to slightly modify the fly (), Do you feel the maintainability is low to the lower limit in an instant?
In this new design method, although the "part" problem was solved, it caused the code to not be reused! Do you feel it? There are more terrible oh, can fly ducks, that flight is not the same, to a somersault 360° rotation this action, what do you want to do? O (∩_∩) o
No matter where you work, in what programming language, in software development, what is the constant truth that accompanies you? (Put the answer you have in mind, write it in the comments ^_^, look forward to your answer)
Make this previous design clear 0 ...
Now we know that using inheritance does not solve the problem very well, because the behavior of ducks is constantly changing in subclasses, and it is inappropriate for those subclasses to have these behaviors, the flyable and quackable interfaces seem to be good and solve the problem (only the Flying Ducks inherit flyable), But this still makes you have a lot of tasks to do, you still can't do code reuse, you are in maintenance, still want to go down, one by one to modify the corresponding behavior.
For this problem, there is now a design principle that can solve this problem, it can implement code reuse, can add and modify to make the system more flexible.
Design Principles:
Find out where applications may need to change, separate them, and don't mix with code that doesn't need to change.
This is some theoretical knowledge, for the skeleton, I will plump out its wings. Keep watching, you will have a harvest!
Now it's time to take out the changes in the Duck Class!
The current variable is the fly and quack related parts that will change, and now separate the two behaviors from the Duck class, creating a new group of classes to represent each behavior.
First to do a flight behavior interface:
public interface Flybehavior
{
void Fly ();
}
The interface of a sip called behavior:
public interface Quackbehavior
{
void Quack ();
}
Have you ever heard of such a design idea:
Programming for interfaces, not for implementation.
and "Programming for interfaces" really means "programming against abstract classes."
The key to "programming for interfaces" is polymorphism. With polymorphism, a program can be programmed against an abstract class, executed in accordance with actual conditions, and not tied to the behavior of an abstract class.
To dig a little deeper, "programming for abstract classes" can be more specifically "the declaring type of a variable, it should be an abstract type, it can be an abstract class, or an interface"! Don't understand it's okay! Next we use the procedure to let everybody slowly to thoroughly grasp this concept!
as a traditional example,:
Programming for implementation:
Dog d = new Dog ();
D.bark ()//"barking" is called behavior
Programming for interfaces or abstract classes:
Animal Animal = new Dog ();
Animal.makesound ()//This method realizes "barking"
You don't get it? It doesn't matter, there are pictures:
Now let's go back to the design of the duck game!
First design flight behavior:
Copy Code code as follows:
Class Flywithwings:flybehavior
{
public void Fly ()
{
Console.WriteLine ("I Can fly! ~! ");
}
}
Class Flynoway:flybehavior
{
public void Fly () {
Do nothing, it can't fly
}
}
I put two classes together, this is convenient for everyone to read, in fact should be separate.
And take a look at the "SIP" called Behavior:
Copy Code code as follows:
Class Quack:quackbehavior
{
public void Quack ()
{
Console.WriteLine ("Sip!");
}
}
Class Squeak:quackbehavior
{
public void Quack () {
Console.WriteLine ("Squeak!") ")//Rubber Duck
}
}
Class Mutequack:quackbehavior
{
public void Quack ()
{
Console.WriteLine ("...");/"Bait duck" will not call
}
}
Act well to realize the duck class
Copy Code code as follows:
Public abstract class Duck
{
Public Flybehavior Flybehavior;
Public Quackbehavior Quackbehavior;
public void Performquack () {
Quackbehavior.quack ();
}
public void Performfly ()
{
Flybehavior. Fly ();
}
Public virtual void swim () {
Console.WriteLine ("~ ~ Tour ~ ~");
}
public virtual void Display () {}
}
The structure is simple, isn't it? The definition of Quackbehavior,flybehavior, each duck will refer to the implementation of Quackbehavior interface objects, let them deal with the behavior of ducks.
Want to sip the effect of the call, it is necessary to Quackbehavior object to sip the call on it, we now do not care about the object of Quackbehavior interface, as long as the relationship duck how to call on the line.
This Quackbehavior interface can be reused, OH. Did you find anything? Where can I reuse it? Think, I'll talk later.
OK, now to specifically implement the Duck entity:
Copy Code code as follows:
public class Mallarduck:duck
{
Public Mallarduck () {
Quackbehavior = new Quack ();
Flybehavior = new Flywithwings ();
}
public override void Display ()
{
Console.WriteLine ("I am a beautiful green-headed duck!") ");
}
}
O (∩_∩) o will be a success, see program:
Copy Code code as follows:
static void Main (string[] args)
{
Mallarduck Mallard = new Mallarduck ();
Mallard. Display ();
Mallard. Swim ();
Mallard.performquack ();
Mallard.performfly ();
}
At a glance, this program to do what, how to do, very simple?
Look at the results of the operation:
The code is also posted, the program does run, and now look at the last concept of this design:
Multi-use combination, less inheritance.
As you can see, using a combination to build a system is very resilient, not just by encapsulating the algorithm family into classes, but by dynamically changing behavior at run time.
Do not know what is "dynamic change behavior at runtime"?
Well, I'll show you one, and take the beautiful green-headed Duck as an example:
Duck Class Latest Modification:
Copy Code code as follows:
Public abstract class Duck
{
Public Flybehavior Flybehavior;
Public Quackbehavior Quackbehavior;
public void Performquack () {
Quackbehavior.quack ();
}
public void Performfly ()
{
Flybehavior. Fly ();
}
Public virtual void swim () {
Console.WriteLine ("~ ~ Tour ~ ~");
}
public virtual void Display () {}
public void Setflybehavior (Flybehavior flyb)//Add extra
{
Flybehavior = Flyb;
}
}
And then I add a rocket power:
Copy Code code as follows:
Class Flyrockepowered:flybehavior
{
public void Fly ()
{
Console.WriteLine ("Beat the Chicken Blood!") 4200 mph, speeding up the flight! ");
}
}
See Program:
Copy Code code as follows:
Class Program
{
static void Main (string[] args)
{
Mallarduck Mallard = new Mallarduck ();
Mallard. Display ();
Mallard. Swim ();
Mallard.performquack ();
Mallard.performfly ();
Mallard. Setflybehavior (New flyrockepowered ());
Mallard.performfly ();
}
}
Results:
Dynamically added, right? Is it easy to modify it?
as for that Quackbehavior interface reuse problem:
You know what, duck-bells? The hunter uses this thing to imitate the duck to call, lures the Wild duck, this is not a very good reuse? O (∩_∩) o more reuse is limited to your imagination ~
If you have carefully read this, the following medal is given to you:
You've learned how to design a strategic person. O (∩_∩) o
You'll never have to worry about any changes in the system.
Policy Person Mode
The algorithm family is defined and packaged so that they can be replaced by each other, and this pattern allows the algorithm to be changed independently of the user using the algorithm.
After reading, if you think it's good, just click on the recommendation. O (∩_∩) o This is for my support, thank you.