Detailed Design Patterns (master)

Source: Internet
Author: User

Reprint: http://www.cnblogs.com/zuoxiaolong/p/pattern1.html

"Introduction"

Speaking of design patterns, the first time I heard, the first reaction is very abstruse, completely understand the meaning of this concept, I will first extract a definition from the Internet.

Design Patterns (designpattern) are a set of reusable, most known, categorized purposes, code design experience Summary.

Above is the explanation of Baidu, to explain the meaning of this simple words, a few key words.

repeated use : This does not have too much to explain, design patterns are used too much, the last series of spring source of the emergence of a lot of patterns, memory of the more profound template mode, proxy mode, single-case mode, Factory mode and so on.

most people know : This does not need to explain too much.

Classification and cataloging : it is said that some features can be found to divide these design patterns, so as to classify.

Code Design Experience : This sentence is very important, design experience summary, that is to say, design patterns, is to guide the design and from experience summed up the routines.

Another argument is that design patterns are a series of ways to solve problems in a particular scenario, and I think the explanation is a bit more pertinent.

"Why Learn Design Patterns"

The above simple introduction, is to let you first understand the design pattern is what, below we say why to learn design patterns, learning always have a driving force.

People who have worked experience know, especially those in the maintenance of a project is more appropriate, like I was one, sometimes, a very simple need, or, should be quickly achievable needs, but because the system was designed without considering the changes in these requirements, Or as the requirements accumulate, the system becomes more and more bloated, resulting in a random modification of a place can cause unpredictable consequences, or I could have modified the configuration file or change a code to solve the problem, the result needs to change the N code to achieve my purpose.

These are very horrible consequences, which I have deeply experienced.

"design pattern benefits and points of attention"

Design patterns can help us improve the design of the system, enhance the robustness of the system, scalability, paving the way for the future.

However, these are the first time I touched the design pattern, I do not think so, the design pattern can improve the design of the system is correct, but too much of the pattern will become complex system. So when we design a system for the first time, please dispose of your definite change point, do not assume that it exists, and if you have done so, change your mind and let the void change point vanish into your mind completely.

Because we can use a different approach to accommodate our change point, that is refactoring, but this is what we have discussed after the design pattern, and now we have to understand all these design patterns, to exercise our design thinking, rather than just a real yards of farmers.

"Guiding principles: Six rules"

Before learning to design patterns, in order not to make design patterns appear to be patterns, we must also understand one thing, that is the six principles of programming.

These principles are the rules of the guiding pattern, and I will attach an example to some principles to illustrate the meaning of this principle, to note that the principle is dead and that people are alive, so you do not want to fully abide by these rules, otherwise the database will have a reverse paradigm, only if possible, please try to comply.

single Duty principle (little Lori in the six rules, people see Love): The description means that each class is only responsible for a single function, must not be too much, and a class should try to maximize a function .

Otherwise, when you go to maintain the system, you will regret your decision, below is my own example of thinking, for your reference, give the code.

Import Java.io.bufferedreader;import java.io.file;import Java.io.filereader;import Java.io.ioexception;public class Calculator {public    int add () throws NumberFormatException, ioexception{        File File = new file ("E:/data.txt"); 
    bufferedreader br = new BufferedReader (new FileReader (file));        int a = integer.valueof (Br.readline ());        int b = integer.valueof (Br.readline ());        return a+b;    }        public static void Main (string[] args) throws NumberFormatException, IOException {        Calculator Calculator = new Calcul Ator ();        SYSTEM.OUT.PRINTLN ("Result:" + calculator.add ());}    }

To see the above example, the function of this method is to read two numbers from a file and return them, and I am sure you can see that there is a clear multi-responsibility problem. If I do not see it, I would like to ask you if I want to count the difference in the two numbers in this document.

I believe the answer should be I copy a Div method, the last plus sign to a minus. Okay, so I'm going to divide it? What about multiplication? Take the mold? Copy it four times. This creates a lot of code duplication, which does not conform to the rules of system design. Let me improve the above procedure.

We separate a class to read the data and look at reader.

Package Com.test;import Java.io.bufferedreader;import Java.io.file;import java.io.filereader;import Java.io.ioexception;public class Reader {        int a, b;        Public Reader (String path) throws NumberFormatException, ioexception{        bufferedreader br = new BufferedReader (new FileReader (new File));        A = Integer.valueof (Br.readline ());        b = integer.valueof (Br.readline ());    }        public int Geta () {        return A;    }        public int Getb () {        return B;    }}

Here is our separate calculator class.

Package Com.test;import Java.io.ioexception;public class Calculator {public    int add (int a,int b) {        return a + b;
    } public        static void Main (string[] args) throws NumberFormatException, IOException {        Reader reader = new Reader ("E:/data.txt");        Calculator Calculator = new Calculator ();        SYSTEM.OUT.PRINTLN ("Result:" + Calculator.add (Reader.geta (), READER.GETB ()));    }    }

We split a class into two classes so that we don't have to repeat the code if we subtract, multiply, and so on.

The above is an example of my temporary fabrication, though very simple and of little practical significance, but I feel that it is sufficient to express the meaning of a single duty and suffice to say its importance. The single principle of responsibility is the principle that I find most likely to be adhered to in the six principles, as I have found in practice that when you follow it in the development of a project, it almost completely does not create any extra complexity for your system, but will make your program look orderly.

The Richter replacement principle (the most quiet girl in the six principles, but not very pleasing): This principle means that a subclass should be able to replace the parent class and work properly .

So the translation into a relatively easy to understand, that is, subclasses should not rewrite the parent class method, because the parent class method is generally published interface, is immutable, you should not change something should not be changed.

The above is only the usual sense of the argument, in many cases, we do not have to understand the Richter scale to replace the quiet girl, such as template method mode, default adapter, decorator mode and some other design patterns, completely ignore this quiet girl.

But even so, if you really met a scene that had to rewrite the parent's method, then consider whether you really want to present this class as a subclass, or whether it will compensate for what you lost, such as a subclass that cannot replace the parent class. Then it means that if your parent can work in a certain scene, then your subclass should be able to do the same, or the following scenario will appear.

For example, we have a class that has a method that invokes a method of a parent class.

One class public class Someoneclass {    //has a method that uses a parent class type public    void Someonemethod (parent parent) {        Parent.method ();    }}

The parent class code is as follows.

public class Parent {public    void method () {        System.out.println (' parent method ');}    }

As a result I have a subclass that overrides the method of the parent class and throws an exception.

public class Subclass extends parent{    //Result A subclass overrides the method of the parent class, saying that the operation is not supported by public    Void Method () {        throw new Unsupportedoperationexception ();    }    }

This exception is run-time only, that is, my someoneclass do not know that this situation will occur, the result is that I call the following code, the original thought is that the parent can be passed to Someonemethod to complete my function, My subclass inherited the parent, of course, but eventually the call throws an exception.

public class Client {public    static void Main (string[] args) {        Someoneclass someoneclass = new Someoneclass (); 
    
     someoneclass.someonemethod (New Parent ());        Someoneclass.someonemethod (new subclass ());}    }
    

This is equivalent to burying a trap, because our principle is that the parent can complete the place, I use sub-class substitution is absolutely no problem, but this is reversed, every time I use a subclass to replace a parent class, I also have to worry about this subclass to bury me a bomb above.

So the Richter replacement principle is a principle that needs our deep understanding, because sometimes we can get a lot of it, lose a small part, but sometimes it is the opposite, so if we want to do ingenious, we must understand the meaning of this principle deeply.


The principle of interface Isolation (the most pick of the six principles, the smallest chest): Also known as the interface minimization principle, emphasizing that an interface has the behavior should be as small as possible .

If you can't do this you will often find this situation, a class implementation of an interface, many of the methods are empty, only a few methods to achieve.

This will not only force the implementation of the people have to implement the method should not be implemented, the most serious is to give the user the illusion that the implementation class has all the behavior of the interface, the result of invoking the method did not reap the desired results.

For example, we design a mobile phone interface, it is necessary to mobile phone which behavior is required, to make this interface as small as possible, or popular point, is that the behavior inside should be such a behavior, that is, as long as the mobile phone, you must be able to do.

The above is the principle of interface isolation This picky woman is critical of the place, if you do not meet her, you may write the following phone interface.

Public interface Mobile {public    void call ();//Phone can be called public        void SendMessage ();//cell phone can send SMS public        void Playbird ();//Mobile can play Angry Birds?    }

The third behavior above is obviously not a mobile phone should have, or not a mobile phone must have, then the interface above this phone is not the smallest interface, assuming I am now a non-smart phone to implement this interface, then the Playbird method can only be empty, because it can not play.

So it's better to get rid of this method, to minimize the mobile interface, and then build the following interface to extend the existing mobile interface.

Public interface SmartPhone extends mobile{public    void Playbird ();//The interface of the smartphone can be added to this method    }

So the two interfaces are minimized, so that our non-smart phone to achieve mobile interface, to achieve the function of telephone and text messaging, and the smart phone to achieve smartphone interface, to achieve the phone, texting and play Angry Birds function, both will not have redundant methods to achieve.

Minimum interface principle generally we want to be satisfied, if there is a redundant method, we also have a remedy, and sometimes it is inevitable that some of the implementation class can not fully implement the method in the interface, this time it is the default adapter to play, this is introduced in the back.

Dependency Inversion principle (the bird Girl of the six principles is very dependent on abstract things): This principle describes that high-level modules should not be dependent on the lower layer modules, both should be dependent on the abstraction, the abstraction should not depend on the details, the details should be dependent on the abstraction .

The above black Bold statement is the original description of this principle, I will explain my own understanding, this principle describes a reality of the fact that the implementation is variable, and only the abstract is stable, so when dependent on the abstraction, the implementation changes will not affect the client's call.

For example, the calculator example above, our calculator is actually dependent on the data read class, this is not very good, because if my data is not in the file, but in the database, so that, in order not to affect your existing code, you can only change your reader class the entire makeover.

Or the other way is, you add a Dbreader class, and then all of your readers using reader to replace all the places, manually replaced with Dbreader, which is also acceptable, that is to say that I have read from the file, some from the database read, some from the XML file read, Some are read from the network, some read from the standard keyboard input, and so on.

What do you want to do?

So our best practice is to abstract an abstract class or interface, to express the behavior of the data read, and then let all the above read methods implemented by the class implementation of this interface, and our client, only use our defined interface, when our implementation changes, I just need to set different actual type on it, This is a big boost for the scalability of the system.

For the above simple data read, we can define the following interface to describe.

Public interface Reader {public    int geta ();        public int Getb ();}

Let our original reader be renamed FileReader to implement this interface, so that the calculator relies on the abstract interface, this dependence is very stable, because no matter where you want to read the data, your two data acquisition method will never change.

In this way, we let dbreader,xmlreader,netreader,standardoutputstreamreader and so on, can implement the reader interface, and our client calls depend on a reader, So no matter where the data comes from, we can handle it, because I don't care what reader you are, I just know you can get me both A and B values.

This is the flexibility that we rely on abstraction, which is the convenience of the dynamic nature of the Java language, so we must cherish this girl who relies on abstraction.

Dimitri Principle (the most shy girl in the six principles, not too fond of talking to strangers): also known as the least known principle, that a class should try not to know the other classes too much, do not have too much contact with unfamiliar classes .

This principle is formulated because if a class knows or relies on another class for too much detail, which causes the coupling to pass high, the details should be all high within the class, and the other classes just need to know the main functionality of the class.

The so-called high cohesion is as far as possible to write the details of a class in the interior of this class, do not leak out to other classes know, otherwise the class will easily depend on these details, so that the coupling between the class will rise rapidly, the consequences of this is often a kind of random pity dorado things, dependent on its classes are all to change.

For example, I'll change the example above.

Import Java.io.bufferedreader;import java.io.file;import java.io.filenotfoundexception;import java.io.FileReader; Import Java.io.ioexception;public class Reader {        int a A, B;        private String path;        Private BufferedReader BR;        Public Reader (String path) {        This.path = path;    }        public void Setbufferedreader () throws filenotfoundexception{        br = new BufferedReader (new FileReader (PATH) ));    }        public void ReadLine () throws NumberFormatException, ioexception{        a = integer.valueof (Br.readline ());        b = integer.valueof (Br.readline ());    }        public int Geta () {        return A;    }        public int Getb () {        return B;    }}

The reader class is changed to this, obviously it reveals too much detail to other classes, let others know it's too much detail, so my client calls when it is possible to write the following form.

public class Client {public    static void Main (string[] args) throws Exception {        Reader reader = new Reader ("E:/tes T.txt ");        Reader.setbufferedreader ();        Reader.readline ();        int a = Reader.geta ();        int b = Reader.getb ();        The following for calculations, etc.    }}

This way the client relies on reader's behavior in order to finally get A and B two values, when the coupling of two classes is too high, we better practice using access restrictions will both be hidden to let the outside call of the class know these. Just like this.

public class Reader {    int a, b;    private String path;    Private BufferedReader BR;    Public Reader (String path) throws exception{        super ();        This.path = path;        Setbufferedreader ();        ReadLine ();    }    Notice that we become private to the method of the privately    void Setbufferedreader () throws filenotfoundexception{        br = new BufferedReader (new FileReader (path));    }    Notice that we become private to the method of the privately    void ReadLine () throws NumberFormatException, ioexception{        a = integer.valueof ( Br.readline ());        b = integer.valueof (Br.readline ());    }        public int Geta () {        return A;    }        public int Getb () {        return B;    }}

We end up with two methods that are privately encapsulated in the reader class so that the outer classes don't know the two methods, so the Dimitri principle is that a class should try not to know the other classes too much detail, but what is more important is that a class should not let the outside classes know that they are too many. The two are mutually reinforcing, as long as you do a good job of encapsulating the class, then the outer class cannot rely on the details.

Open-Close principle (the six principles of absolute eldest sister, the other five sisters willingly surrender): The last principle, a word, to modify the closed, open to the extension .

That is, I do not need to change any of the original code, and only need to add some new implementation, you can achieve my purpose, which is the ideal state of system design, but no one system can do this, even if I have always admired the spring framework does not, although its extensibility has been strong to metamorphosis.

This principle is more like the first five principles of the master, the first five principles is around it, as long as we try to comply with the first five principles, then the design of the system should be more in line with the open and close principle, on the contrary, if you violate too much, then your system may also not follow the open and close principle.

In "Big talk design Mode" a book, mention a sentence with you to encourage, I feel very convincing, that is, with abstract framework, with the details to achieve expansion .

The above six principles are written in order to guide the description of the design pattern behind, the basic is the understanding of my own experience, perhaps there are good and bad, there are poor, you do not need to care too much about the form of expression, can have their own understanding.

Next announcement: Singleton mode.





Detailed Design Patterns (master)

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.