common design patterns

Design patterns are often divided into three categories:

    Creation type: When creating an object, the object is not instantiated directly; instead, the application program determines the way to create an object according to a specific scenario, thereby ensuring higher performance and better architectural advantages. The creational patterns mainly include simple factory pattern, factory method, abstract factory pattern, single-column pattern, generator and prototype pattern.

    Structural: Used to help organize multiple objects into larger structures. Structural patterns mainly include adapter pattern, bridge pattern, combiner pattern, decorator pattern, facade pattern, flyweight pattern and proxy pattern.

    Behavioral: Used to help communicate between objects in a system and how to control processes in complex systems. Behavioral patterns mainly include command pattern, interpreter pattern, iteration pattern, mediator pattern, memorandum pattern, state pattern, strategy pattern, template pattern, and access pattern.

1. Single-column mode

      Sometimes it doesn't make sense to create an instance of a class freely, and it may cause system performance degradation (because of the system overhead caused by creating objects).

     Main points:

           1) Modify the constructor with private

           2) Provide a public static method for obtaining objects of this class

           3) The class needs to cache an already created object, otherwise the class cannot know whether the object has been created.

        An example is as follows:

           class Singleton{

                 private static Singleton instance;

                 private Singleton(){

                   }

                  public static Singleton getInstance(){

                       if(instance == null){

                             instance = new Singleton();

                          }

                         return   instance;

                   }

                }

 

2. Simple Factory Pattern

     The design approach of passing multiple objects to a factory to generate is known as the simple factory pattern.

      For example class A depends on class B. For class A, it does not care about the implementation and creation process of object B. Consider that class B implements an IB interface, and class A only needs to be coupled with the IB interface - class A does not directly use the new keyword to create an instance of B, but redefines a factory class: IBFactory, which is responsible for creating IB Implementation, and class A gets an instance of IB by calling the method of the IBFactory factory.

      The following is a simple example to illustrate the simple factory pattern: Suppose there is a Computer object that needs to depend on an output device (Printer object). Let the Computer class depend on the output attribute, and separate the computer class from the printer class. The Computer object only needs to be programmed for the output interface. It is completely transparent which implementation class the computer object depends on.

      public class Computer{

            private Output out;

            public Computer (Output out){

                this.out = out;

             }

          public void keyIn(String msg){

                 out.getData(msg);

           }

           public void print(){

               out.out();

            }

         public static void main(String[] args){

            outputFactory of =new outputFactory ();

            Computer c = new Computer(of.getOutput());

            c.keyIn("lightweight java");

            c.print();

         }

     }

The above code shows that the computer class and the printer class have been separated, but are only coupled with this interface. And Computer is no longer responsible for creating output objects, the system will provide an Output factory class responsible for generating output objects, the outputFactory factory class is as follows:

          public class OutputFactory{

                   public Output getOutput(){

                       return new Printer();

                  }

             }

     The above class provides a getOutput() method, which returns an output instance, which is responsible for creating an output instance, and which implementation class object to create is determined by this method.

        Program list: Printer.java code is as follows:

             public class Printer{

                     private String[] printData = new String[MAX_CACHE_LINE);

                       //Used to record the number of pages currently to be printed

                     private int dataNum=0;

                     public void out(){

                            //z As long as there are jobs, continue printing

                            System.out.println("Printer print: " + printData[0];

                             // Move the entire job queue forward by one, and decrement the number of remaining jobs by one

                            System.arraycopy(printData,1,printData,0,--dataNum);

                      }

                }

               public void getData(String msg){

                          if(dataNum >= MAX_CACHE_LINE){

                                 System.out.println("The output queue is full, adding failed");

                            }else{

                                 printData[dataNum++] = msg;

                            }

                 }

           }

     The above printer class simulates a simple printer. If the system needs to be refactored and needs to use BetterPrinter instead of the Printer class, you need to let the BetterPrinter output interface and change the getOutput() method of the OutputFactory class.

      Change the getOutput() method of the OutputFactory class to the following:

            return new BetterPrinter();

   In this way, all the logic for generating Output objects can be managed in the OutputFactory factory class. All classes that require Output objects need to be coupled with the Output interface instead of the specific implementation classes, even if there are many classes in the system that depend on Printer object, just modify the getOutput() method of the OutputFactory class to return the BetterPrinter object.

        The advantage of using the simple factory pattern is to separate the caller of the object from the creation process of the object. When the caller of the object needs the object, it can directly request the factory, thus avoiding the hard-coded coupling between the invocation of the object and the implementation class of the object. To provide system maintainability and scalability. But the factory pattern has a small flaw: when the product is modified, the corresponding factory class also needs to be modified.

 

3. Abstract Factory

    In the simple factory mode, the system uses the factory class to produce all product instances, and the factory class decides which class to produce, that is, the factory class is responsible for all logical judgments and instance creation.

    If you don't want to make logical judgments in the factory class, the program provides different factories for different product classes, and different factory classes produce different products. For example, PrinterFactory and BetterFactory factory classes are provided for the above Printer and BetterPrinter.

    This example uses the outputFactory in 2 as an interface, and provides two implementation classes for the interface: PrinterFactory and BetterPrinterFactory 

     OutputFactory interface code such as:

      public  interface OutputFactory{

          Output getOutput();

       }

       The PrinterFactory implementation class is as follows:

         public class PrinterFactory implements  OutputFactory{

              public Output getOutput(){

                 return new Printer();

             }

           }

       The BetterPrinterFactory  implementation class is as follows:

            public class BetterPrinterFactory implements  OutputFactory{

              public Output getOutput(){

                 return new BetterPrint();

             }

           }

    The Couputer class in modification 2 is as follows:

               public class Computer{

            private Output out;

            public Computer (Output out){

                this.out = out;

             }

          public void keyIn(String msg){

                 out.getData(msg);

           }

           public void print(){

               out.out();

            }

         public static void main(String[] args){

            outputFactory of =new PrinterFactory ();

            Computer c = new Computer(of.getOutput());

            c.keyIn("lightweight java");

            c.print();

         }

     }

    When the program needs to call the methods of the Output object, it needs to explicitly create different factory instances. What is created in the program is the PrinterFactory  instance. Although this method will not modify the method of the factory class, it will bring another kind of coupling, the coupling between the client code and the factory class.

    In this mode, a new OutputFactoryFactory factory class is added, and the modified factory class provides a getOutputFactory(String type) method, which is used to return an OutputFactory factory example. Here is the code of OutputFactoryFactory:

        public class OutputFactoryFactory{

               public static  OutputFactory  getOutputFactory(String type){

                       if(type.equalsIngnoreCase("better"){

                           return new BetterPrinterFactory();

                         }else{

                             return new PrinterFactory();

                         }

                  }

            }

        Modify the Mian method of the Computer class as follows:

        public static void main(String[] args){

              outputFactory of =OutputFactoryFactory.getoutputFactory("better");

            Computer c = new Computer(of.getOutput());

            c.keyIn("lightweight java");

            c.print();

        }

   The above program is used to generate an OutputFactory factory, but which factory to generate is determined by the OutputFactoryFactory abstract factory. Different factories produce different output objects. By using the abstract factory pattern, the system can let the client code and the called object implement classes, The concrete factory class implements separation.

     If the factory directly produces the called object, it is the simple factory pattern, and if the factory produces the factory object, it is upgraded to the abstract factory pattern.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326682053&siteId=291194637