23 Design patterns necessary for programming __ programming

Source: Internet
Author: User
Tags memory usage reflection serialization shallow copy static class

We recommend that you learn programming when you must look at the algorithm to see how the bottom of the implementation, regardless of learning any language, I believe that design patterns must be well known, this article in the Java language as a representative, explained 23 design patterns, and there are examples. I wish you all learn progress, QQ group 127591054.

design mode Recommendation book: head

Design patterns are a set of repeated use, most people know, through the classification of purpose, code design experience Summary.
Design patterns are used in order to reuse code, make code easier for others to understand, and ensure code reliability. There is no doubt that design patterns in others in the system are more win, design patterns so that the code is really engineering, design pattern is the cornerstone of software engineering, like a block of bricks and stones in the building.
The rational use of design patterns in the project can perfectly solve many problems, each pattern now has a corresponding principle in place, each of which describes a recurring problem around us and the core solution to the problem, which is why it is widely used. I. Classification of design Patterns

The creation pattern, altogether five kinds: The factory method pattern, the abstract factory pattern, the single case pattern, the builder pattern, the prototype pattern.

Structure mode, a total of seven kinds: Adapter mode, adorner mode, agent mode, appearance mode, bridging mode, combination mode, enjoy meta mode.

There are 11 types of behavioral Patterns: Policy mode, template method pattern, observer mode, iterator mode, responsibility chain mode, Command mode, Memo mode, state mode, visitor mode, mediator mode, interpreter mode. Second, Java 23 design pattern

1. Factory mode (Factory method)

The factory method pattern is divided into three kinds: Common Factory mode   multiple factory method mode   static Factory method pattern

1.1, Common Factory mode, is to create a factory class, to implement the same interface of the Product class for instance creation

Example://Send SMS and Mail interface public interface Sender {public void send (); The implementation class public class MailSender implements Sender {public void Send () {System.out  
        . println ("Send mail!"); }///Send SMS Implementation class public class Smssender implements Sender {public void Send () {Sys  
        TEM.OUT.PRINTLN ("Send SMS!");  
            }///Create factory class public class Sendfactory {//factory method public Sender produce (String type) {  
            if ("Mail". Equals (Type)) {return new MailSender ();  
            else if ("SMS". Equals (Type)) {return new Smssender ();  
                else {System.out.println ("Please enter the correct type!");  
            return null;  
            }}//test class public class Factorytest {public static void main (string[] args) {  
            Sendfactory factory = new Sendfactory (); Sender Sender = Factory.produce ("SMS"); Sender.  
        Send ();  }  
    }

1.2. More than one factory method pattern is an improvement of the normal factory method pattern, in the normal factory method mode, if the string is passed incorrectly, the object is not created correctly, and multiple factory method patterns provide multiple factory methods to create the object separately.

Modify the above code, change the Sendfactory class on the line
    //This does not have to create objects based on user-transmitted string classes public
    class Sendfactory {public  

        Sender Producemail () {return  
            new MailSender ();  
        }  

        Public Sender producesms () {return  
            new Smssender ();  
        }  
    }

    Test class public
    class Factorytest {public  

        static void Main (string[] args) {  
            Sendfactory factory = new SENDFAC Tory ();  
            Sender Sender = Factory.producemail ();  
            Sender. Send ();  
        }  
      

1.3, Static factory method mode, the above multiple factory method mode to static, do not need to create an instance, direct call can be.

public class Sendfactory {public  

        static Sender Producemail () {return  
            new MailSender ();  
        }  

        public static Sender Producesms () {return  
            new Smssender ();  
        }  
    }  

    Test class public
    class Factorytest {public  

        static void Main (string[] args) {      
            Sender Sender = Sendfactory.produc EMail ();  
            Sender. Send ();  
        }  
       

2. Abstract Factory Model (abstracts Factory)
Factory method Pattern There is a problem is that the creation of classes rely on the factory class, that is, if you want to expand the program, you must modify the factory class, which violates the closure principle, so from the design point of view, there are certain problems, how to solve. Use the abstract factory pattern to create multiple factory classes so that once you need to add new functionality, you can add new factory classes directly, without needing to modify the previous code.

        Example://Send SMS and Mail interface public interface Sender {public void send (); The implementation class public class MailSender implements Sender {public void Send () {System.out  
        . println ("Send mail!"); }///Send SMS Implementation class public class Smssender implements Sender {public void Send () {Sys  
        TEM.OUT.PRINTLN ("Send SMS!");  
    }//to the factory class an interface public interface Provider {public Sender produce ();  
            ///Two Factory implementation class public class Sendmailfactory implements Provider {public Sender produce () {  
        return new MailSender (); } public class Sendsmsfactory implements provider{public Sender produce () {return  
        New Smssender (); }//test class public class Test {public static void main (string[] args) {Provider  
            Provider = new Sendmailfactory (); Sender Sender= Provider.produce (); Sender.  
        Send ();  }  
    }

Note: The advantage of this model is that if you now want to add a function: Send timely information, you need to do a realization class implementation sender interface, at the same time to do a factory class, implement Provider interface, OK, no need to change ready-made code. This is a good extension of

3. Single case mode (Singleton)
A single Example object (Singleton) is a common design pattern. In Java applications, a singleton object can guarantee that only one instance of the object exists in a JVM. There are several benefits to this pattern:
1, some classes to create more frequent, for some large objects, this is a large amount of system overhead.
2, eliminates the new operator, reduces the system memory usage frequency, reduces the GC pressure.
3, some classes, such as the exchange's core trading engine, control the transaction process, if the class can create multiple words, the system is completely chaotic.

    Example:
    //Simple Singleton class  a hungry man mode public
    class Singleton {/  

        * holds private static instances to prevent being referenced/  
        private Singleton instance = New Singleton ();  

        /* Private construction method to prevent being instantiated  
        /private Singleton () {  
        }/  

        * Static Engineering method, return Singleton instance/public  
        static Singleton GetInstance () {return  
            instance;  
        }  

        /* If the object is used for serialization, the object can be guaranteed to remain consistent before and after serialization * *  
        Private Object Readresolve () {return  
            instance  
        }  
    }  

This class can be implemented in singleton mode, but there are many problems, such as in the class regardless of whether the user wants to use the object of the class, first created an instance put in memory.

    Simple Singleton class Lazy mode public
    class Singleton {/  

        * holds a private static instance to prevent reference, where the assignment is null to implement deferred loading/  
        private static Singleton instance = null;  

        /* Private construction method to prevent being instantiated  
        /private Singleton () {  
        }/  

        * Static Engineering method, create instance  
        /public static Singleton getinstance () {
  if (Instance = = null) {  
                instance = new Singleton ();  
            }  
            return instance;  
        }  

        /* If the object is used for serialization, the object can be guaranteed to remain consistent before and after serialization * *  
        Private Object Readresolve () {return  
            instance  
        }  
    }  

This class can meet the basic requirements, but, like such a thread-safe class, if we put it into a multithreaded environment, there will certainly be problems, how to solve. We will first think of the getinstance method plus synchronized keyword, as follows:

    public static synchronized Singleton getinstance () {  
        if (instance = = null) {  
            instance = new Singleton ();  
        } return  
        instance;  
    }   

However, synchronized is used as a modifier on the method and will degrade in performance, because each time you call getinstance (), you lock the object, in fact, you need to lock the object for the first time, and then you don't need it, so this place needs to be improved. Let's change this to the following:

public static Singleton getinstance () {  
        if (instance = null) {  
            synchronized (instance) {  
                if (instance = null {  
                    instance = new Singleton ();  
        }}} return instance;  
    }  

It seems to solve the previously mentioned problems, add the Synchronized keyword in the method inside, that is, when the call is not required to lock, only in instance null, and create objects when the need to add locks, performance has a certain degree of improvement. However, there may be problems with this situation.

See the following scenario: creating objects and assigning operations in Java directives is done separately, that is, instance = new Singleton (); The statement is not an atomic operation, and in the JVM this code probably does the following 3 things:

    1 allocating memory to new objects
    2 invokes the Singleton constructor to initialize the member variable
    3 refers instance to the allocated memory space (instance is not NULL after this step)

However, there is an optimization of instruction reordering in the JVM's Just-in-time compiler. In other words, the order of the second and third steps above is not guaranteed, and the final order of execution may be 1-2-3 or 1-3-2. If this is the latter, then after 3 execution, 2 does not execute, another thread B rob the CPU's execution power, then instance has been non-null (but not initialized), so thread B will return directly to instance, and then use, the result will be a problem ( Because the object is not initialized yet).

There is another solution: using an internal class to maintain the implementation of a single instance, the internal mechanism of the JVM ensures that when a class is loaded, the loading process of the class is thread-mutually exclusive (that is, the other threads will not be able to use it after loading). So when we first call getinstance, the JVM can help us make sure that the instance is created once and that the memory assigned to instance is initialized so that we don't have to worry about the problem above. At the same time, this method will only use the mutex mechanism at the first call, which solves the low performance problem.

For example: Public

    class Singleton {  

        /* Private constructor method, prevent being instantiated  
        /private Singleton () {  
        }  

        * * Here use an internal class to maintain the singleton * *  
        private static class Singletonfactory {  
            private static Singleton instance = new Singleton ();  
        }  

        /* Get instance  
        /public static Singleton getinstance () {return  
            singletonfactory.instance;  
        }  

        /* If the object is used for serialization, the object can be guaranteed to remain consistent before and after serialization * *  
        Private Object Readresolve () {return  
            getinstance ()}  
    }

However, if you throw an exception in the constructor, the instance will never be created and there will be an error. So, the perfect thing is not, we can only according to the actual situation, choose the most suitable for their own application scenario implementation.

At the same time, we can also use reflection to create objects of this class, even if its constructor is private, we can call it. So this time we'll need to modify the code again to access the other person's reflection call builder.

    Example:
    //control in the constructor, the constructor allows only one call at a time, and then throws an exception on the call on the public
    class Singleton {  
        private static Boolean flag;
        /* Private construction method to prevent being instantiated  
        /private Singleton () {  
            if (!flag) {
                flag = false;
            } else{
                throw new RuntimeException ("Cannot create a single instance object more than once");
            }  

        /* Here an internal class is used to maintain the single example  
        /private static class Singletonfactory {  
            private static Singleton instance = new Singleton () ;
        }  

        /* Get instance  
        /public static Singleton getinstance () {return  
            singletonfactory.instance;  
        }  

        /* If the object is used for serialization, the object can be guaranteed to remain consistent before and after serialization * *  
        Private Object Readresolve () {return  
            getinstance ()}  
    }   

The problem with reflection is that if you serialize the single object and then deserialize it, there will be two identical single instances in memory, except for the memory address. In this case we can use the Readresolve method to prevent.

    Private Object Readresolve () {...} ObjectInputStream checks whether the object's class defines the Readresolve method. If defined, the returned object is specified by the Readresolve method. 
    Returns the type of the object must be compatible, otherwise it throws a classcastexception. Example: Public abstract class Singleton8 implements serializable{private static final long Serialversionuid =

        7863921642928237696L;
            /* Here an internal class is used to maintain the single example/private static class Singletonfactory {@SuppressWarnings ("serial")
        private static Singleton8 instance = new Singleton8 () {};  
                ///testing method, serializing a single instance object and deserializing it to get a new object is equivalent to replicating a single Instance object public Singleton8 copy () throws exception{ (Bytearrayoutputstream is also invoked after the slip is closed and does not produce any exception) Bytearrayoutputstream OS = new Bytearrayoutput  
                Stream ();  
                ObjectOutputStream oos = new ObjectOutputStream (OS);  

                Oos.writeobject (Singleton8.getinstance ());  
                InputStream is = new Bytearrayinputstream (Os.tobytearray ()); ObjectInputStream ois = new ObjectInputStream (IS);  
                Singleton8 obj = (Singleton8) ois.readobject ();  
        return obj;  
        /* Get instance/* public static Singleton8 getinstance () {return singletonfactory.instance;  }/* If the object is used for serialization, you can ensure that the object is consistent before and after serialization * * * Put this method comment before and comment later run test code observation results/private Object  
        Readresolve () {return getinstance (); Finally, consider one more question: can I use enumerations to implement a single case pattern?

The

4, builder mode (Builder)
Factory class pattern provides a pattern for creating a single class, while the builder pattern is to centralize the various products for the purposes of creating composite objects, which are called composite objects that have different properties for a class. The builder model is used primarily to "step through a complex object", where "step-by" is a stable algorithm, while the parts of complex objects often change. Therefore, the builder model is mainly used to solve the demand change of "object part". This allows finer control over the process of object construction.

        Example://CPU interface public interface CPU {}//inter's Cup class INTELCPU implements cpu{}// AMD CPU class AMDCPU implements cpu{}//Memory interface public interface Memory {}//Kingston memory Class Kin Gstonmemory implements memory{}//Samsung memory class Samsungmemory implements memory{}//Motherboard memory public Interface Mainboard {}/ASUS Motherboard class Asusmainboard implements mainboard{}/Gigabyte motherboard class Gamainbo  
        ARD implements mainboard{}//Computer public class Computer {private CPU CPU;  
        Private Memory Memory;
        Private Mainboard mainboard;    
        Get/set}//The Builder interface of the computer is public interface Computerbuilder {public void buildcpu ();    
        public void buildmemory ();    
        public void Buildmainboard ();   
    Public Computer getcomputer ();  
}//Lenovo computer's builder public class Lenovecomputerbuilder implements Computerbuilder {       Private Computer Lenovecomputer;    
       Public Lenovecomputerbuilder () {lenovecomputer = new Computer ();  
       public void Buildcpu () {lenovecomputer.setcpu (New intelcpu ());  
       public void Buildmemory () {lenovecomputer.setmemory (New kingstonmemory ());  
       public void Buildmainboard () {Lenovecomputer.setmainboard (New Asusmainboard ());  
       Public Computer Getcomputer () {return lenovecomputer; }//HP PC Builder public class Hpcomputerbuilder implements Computerbuilder {private Computer    

       Hpcomputer;  
       Public Hpcomputerbuilder () {hpcomputer = new Computer ();  
       public void Buildcpu () {hpcomputer.setcpu (New amdcpu ());  
       public void Buildmemory () {hpcomputer.setmemory (New samsungmemory ()); } public void BuildMainboard () {Hpcomputer.setmainboard (New Gamainboard ());  
       Public Computer Getcomputer () {return hpcomputer;     
        }//director Class (Director)//guide How to specifically create a computer public class Director {private Computerbuilder builder;     
        Public Director (Computerbuilder builder) {this.builder = builder;
            }//user-defined custom order specifically instructs various builder how to create a computer public void construct () {builder.buildcpu ();
            Builder.buildmemory ();
        Builder.buildmainboard (); }//test class public class Test {public static void main (string[] args) {Computer Lenovecompu    
                ter = null;    
        Computerbuilder Lenovecomputerbuilder = new Lenovecomputerbuilder ();
        Director Director = new Director (Lenovecomputerbuilder);
        Director.construct ();
        Lenovecomputer = Lenovecomputerbuilder.getcomputer (); SYSTEM.OUT.PRINTLN (lEnovecomputer);   }
    }

From this point of view, the builder model integrates many functions into a class that can create more complex things. So the difference with the engineering model is that the factory model is concerned with creating a single product, while the builder pattern focuses on creating multiple parts that fit the object. Therefore, choose the factory model or the builder model, depending on the actual situation.
For example, a person class is composed of three objects of the header, the body, and the foot, so we need to create these three parts separately in the builder pattern and then assemble them into a person object.

5. Prototype mode (Prototype)
Although the prototype model is a model of creation, it has nothing to do with engineering mode, and the idea of the model is to use an object as a prototype, copy it, clone it, and produce a new object similar to the original object. In Java, replication objects are implemented through clone (), creating a prototype class first:

    public class Prototype implements cloneable {public  

        Object clone () throws Clonenotsupportedexception {  
            Prototype proto = (Prototype) super.clone ();  
            return proto  
        }  
    }  

Very simple, a prototype class, only need to implement the Cloneable interface, overwrite the Clone method, where the Clone method can be changed to any name, because the Cloneable interface is an empty interface, you can arbitrarily define the method name of the implementation class, such as Clonea or CLONEB, Because the point here is Super.clone (), Super.clone () calls the object's clone () method, and in the object class, the Clone () is native, indicating that the method implementation is not using the Java language.

Here we get to know two concepts: shallow copy deep copy, shallow copy: When an object is copied, a variable of the base data type is recreated, and the reference type is pointed to or pointed to by the original object.

Deep copy: After copying an object, both the base data type and the reference type are recreated. In short, the deep copy is completely copied, and the shallow copy is not thorough.

    public class Prototype implements Cloneable, Serializable {  

        private static final long serialversionuid = 1L;  
        private string string;  
        This is a class p declared below
        

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.