当前位置:网站首页>Creator mode summary

Creator mode summary

2022-06-22 19:34:00 OldZhangYH

Source code address

The singleton pattern

The singleton pattern ensures that only one object of this class is created in the entire system . He provides a way to access his only object , You can directly access , No additional instantiation of the object is required .
The singleton pattern has several salient features :

  1. Privatized construction method , So you can't create objects by constructing methods .
  2. Provide external static methods to allow external access to objects .
  3. Privatize static variables , To ensure that there is only one global variable .

classification

Singleton patterns fall into two categories :

  1. Hungry Chinese style : The object will be created when the class is loaded
  2. Slacker type : The object will not be created when the class is loaded , The class will be created when it is first used .

There are several ways to realize the starved Han style

Objects are generated when the class is loaded , But it's a waste of memory if you don't use it .

Static variable method

public class HungrySingleton1 {
    
    private HungrySingleton1(){}

    private static HungrySingleton1 instance=new HungrySingleton1();

    public static HungrySingleton1 getInstance(){
        return instance;
    }

}

Static code block method

public class HungrySingleton2 {
    private HungrySingleton2(){}

    private static HungrySingleton2 instance;

    static{
        instance=new HungrySingleton2();
    }
    public static HungrySingleton2 getInstance(){
        return instance;
    }
}

The two methods mentioned above are actually similar , It's in the class new A private static variable , Then the external method only returns him .

Use enumeration class to implement singleton pattern

public enum HungrySingleton3 {
    INSTANCE;
    public void method1(){
        System.out.println("do sth");
    }
}

How is it very simple , And the implementation of enumeration classes is the safest . Will not be reflected or serialized .

Several ways to realize the lazy style

Lazy when classes are used , To avoid the waste of memory .

Thread unsafe lazy

This method is to call getInstance() Method to determine whether an object has been created . If it is created, it returns , No, just create one in return . But in the case of multithreading , There may be a phenomenon of secondary creation .

public class Lazy1 {
    private Lazy1() {
    }

    private static Lazy1 instance;

    public static  Lazy1 getInstance() {
        if (instance == null) {
            instance=new Lazy1();
        }
        return instance;
    }
}

The lazy side of thread safety

The difference from the above is that there is one more synchronized keyword . Use synchronized Key words to getInstance() Methods locking , But the lock is added to the whole method , But the performance is poor .

public class Lazy1 {
    private Lazy1() {
    }

    private static Lazy1 instance;

    public static synchronized Lazy1 getInstance() {
        if (instance == null) {
            instance=new Lazy1();
        }
        return instance;
    }
}

Double check mode

Double check lock mode , Put the lock in the method instead of the whole method . You only need to obtain a lock when you need to create an object , Make the granularity of the lock finer . More efficient .

public class Lazy2 {
    private Lazy2(){}
    //volatile  To ensure the order of instructions , Otherwise, in a multithreaded environment   because jvm Reordering instructions of may cause null pointers 
    private static volatile Lazy2 instance;

    public static Lazy2 getInstance(){
        if(instance==null){
            synchronized(Lazy2.class){
                if(instance==null){
                    instance=new Lazy2();
                }
            }
        }
        return instance;
    }
}

Static inner class pattern

Hold the object by creating a static inner class inside the object . Static inner classes are not loaded when the class is loaded , It is loaded only when it is called , Thus, the lazy type . And it's thread safe .

public class Lazy3 {
    private Lazy3(){}    

    private static class Lazy3Holder{
        private static final Lazy3 INSTANCE=new Lazy3();
    }
    public static Lazy3 getInstance(){
        return Lazy3Holder.INSTANCE;
    }
}

problem

serialize 、 Deserialization breaks the singleton pattern

Let's start with the basic concepts ,

  1. serialize : Convert object to byte stream , Then write to file or transfer to other terminals through the network .
  2. Deserialization : Convert the byte stream back to an object .
    So we serialize classes into byte streams , And then save it to a file . You can create objects .
    public static void write2File() throws FileNotFoundException, IOException {
        Lazy2 l = Lazy2.getInstance();
        ObjectOutputStream oStream = new ObjectOutputStream(new FileOutputStream("obj.txt"));
        oStream.writeObject(l);
        oStream.close();
    }

Then it is de sequenced into objects through byte stream .

    public static Lazy2 read4File() throws FileNotFoundException, IOException, ClassNotFoundException{
        ObjectInputStream oInputStream=new ObjectInputStream(new FileInputStream("obj.txt"));
        Lazy2 l=(Lazy2)oInputStream.readObject();
        oInputStream.close();
        return l;
    }

We directly deserialize twice , Generate two objects . The output is :false. It shows that we have generated two different objects , It destroys the global unique object property of singleton mode .

    public static void main(String[] args) throws Exception{
        write2File();
        System.out.println(read4File()==read4File());
    }

Reflection cracking singleton mode

Reflection can be through a class corresponding to class Class to get this class all Member variables and methods of , Whether private or public .
It can be understood as , Each class has a gate . Inside the door are his private variables and methods , Only the class has its own key to open the door to operate them . But reflection does not speak of martial virtue , He has a chainsaw . Saw the door open , Then operate on the private variables and methods of this class .

public class Reflection {
    public static void main(String[] args) throws Exception{
        // obtain Lazy2 Of class class 
        Class<Lazy2> class1=Lazy2.class;
        // Get private constructor 
        Constructor con=class1.getDeclaredConstructor();
        // Violent break ( Set private methods accessible )
        con.setAccessible(true);
        // Use construction methods to create objects 
        Lazy2 l=(Lazy2) con.newInstance();
        Lazy2 l2=(Lazy2) con.newInstance();
        System.out.println(l==l2);
    }
}

Output :false

Solution

The following examples are all in Lazy2 Last modified

serialize 、 Deserialization

Add... To the singleton pattern class that requires serialization and deserialization readResolve() Method to specify the return value of deserialization .
During deserialization ,Java Will determine whether there is this function , If yes, return the return value of this function . If it doesn't, it will new A new object to return

    public Object readResolve(){
        return instance;
    }
 public static void main(String[] args) throws Exception{
        write2File();
        Lazy2 l=read4File();
        Lazy2 l2=read4File();
        System.out.println(l==l2);
    }

Output :true

Reflection

Since the reflection is realized by calling the constructor to create the object , Then we will add a little logical judgment to the construction method , An error is reported when there is an object , Just don't let him create it .

private Lazy2(){
        synchronized(Lazy2.class){
            if(instance!=null){
                throw new RuntimeErrorException(null, " Do not create multiple objects ");
            }
        } 
    }

After a regular call , When using reflection to create an object, an error will be reported .

    Lazy2 l=Lazy2.getInstance();
    Lazy2 l1=(Lazy2) con.newInstance();

But it can still be cracked by using reflection directly

Lazy2 l1=(Lazy2) con.newInstance();
Lazy2 l2=(Lazy2) con.newInstance();

The reflex is really too strong

Enumeration method is good !

Java The standard word stipulates , Each enumeration type and its defined enumeration variables are in JVM All of them are unique . Perfect for singleton mode !

Simple factory model

Use an interface A To specify the specifications of the products produced by the factory . Then use this interface A To describe the actual production products .

give an example

Our program needs to output logs

public class Log {
    public void log(String name){
        if (name.equals("txt")) {
            System.out.println(" Go to txt Output data in ");
        } else if (name.equals("cmd")) {
            System.out.println(" Go to CMD Output data in ");
        } 
    }
}

But in general , We have many kinds of Log class , If each Log Classes can go to txt And output logs from the command line . Suppose there is n Kind of Log class , So we have to write this code n Time , This is not a big problem . But suddenly one day , You need to log into a database , Then we need to modify the above code , To such .

public class Log {
    public void log(String name){
        if (name.equals("txt")) {
            System.out.println(" Go to txt Output data in ");
        } else if (name.equals("cmd")) {
            System.out.println(" Go to CMD Output data in ");
        } else if(name.equals("db")){
            System.out.println(" Output logs to the database ");
        }
    }
}

It's easy to change it once , But don't forget We have n individual Log class , This is going to kill me . We're going n Change in one place , And forgetting to change it will lead to system errors .
So we can use the simple factory model .

  1. Abstract out a Log product
    Let's define a Log Interface Log The function of .
public interface Log{
   public void writeLog();
}
  1. Write implementation class CMDLog,TxtLog To express concretely Log Class ( Specific products )
public class CMDLog implements Log{
    @Override
    public void writeLog() {
        System.out.println(" Go to CMD Output data in ");
        
    }
}
public class TxtLog implements Log{
    @Override
    public void writeLog() {
        System.out.println(" Go to txt Output data in ");
    }
}
  1. Define a LogFactory The factory comes back Log product
public class LogFactory {
    public static Log createLog(String name) {
        if (name.equals("txt")) {
            return new TxtLog();
        } else if (name.equals("cmd")) {
            return new CMDLog();
        } else {
            return null;
        }
    }
}
  1. Different Log Call the factory to get Log Implementation class , Conduct business operations
public class ApacheLog {
    public void log(String name){
        Log log=LogFactory.createLog(name);
        log.writeLog();
    }
    public void ApacheLogMethod(){
        System.out.println("Apache Log specific methods ");
    }
}
public class SysLog {
    public void log(String name){
        Log log=LogFactory.createLog(name);
        log.writeLog();
    }
    public void sysLogMethod(){
        System.out.println(" System log exclusive method ");
    }
}

SysLog and ApacheLog They all have their own way , But you can output logs anywhere at will , Although it was used in the end if/else To determine where to output logs , But when we need to add new requirements , We just need to modify it LogFactory And add an implementation class . There is no need to modify SysLog and ApacheLog 了 .

test

 public static void main(String[] args) {
        ApacheLog apacheLog=new ApacheLog();
        SysLog sysLog=new SysLog();

        apacheLog.log("txt");
        apacheLog.ApacheLogMethod();

        sysLog.log("cmd");
        sysLog.sysLogMethod();
    }

Output :
Go to txt Output data in
Apache Log specific methods
Go to CMD Output data in
System log exclusive method

advantage :

  1. A caller wants to create an object , Just know its name .
  2. High expansibility , If you want to add a product , Just extend a factory class .
  3. The concrete realization of shielding products , The caller only cares about the interface of the product .

shortcoming :

Every time you add a product , We need to add a concrete class and object implementation factory , Make the number of classes in the system multiply , To a certain extent, it increases the complexity of the system .

Use scenarios :

  1. Loggers : Records may be recorded to the local hard disk 、 system event 、 Remote server, etc , Users can choose where to log .
  2. Database access , When the user does not know which kind of database the final system uses , And when the database may change .
  3. Design a framework to connect to the server , Three agreements are needed ,“POP3”、“IMAP”、“HTTP”, You can think of these three as product categories , Jointly implement an interface .

matters needing attention

As a way to create a class pattern , Where complex objects need to be generated , You can use the factory method pattern . One thing to note is that complex objects are suitable for factory patterns , And simple objects , In particular, only through new You can complete the created object , No need to use factory mode . If you use factory mode , You need to introduce a factory class , It will increase the complexity of the system .

Factory method model

Compared with the simple factory model , The factory method mode fully conforms to the opening and closing principle ( Turn off for changes , Open to expansion )

Concept

The factory method pattern defines a factory interface for creating objects , Then let its subclasses decide which object to create . Factory methods delay the creation of a product class into its factory subclasses .

structure

  1. Abstract factory : Provide the interface to create the product , It allows you to access specific factories and create products
  2. Specific factory : Implementation subclass of abstract factory , The method that implements the abstract factory , Finished creating product
  3. Abstract product : Defines product specifications , Describes the functions and features of the product
  4. Specific products : Implementation subclasses of abstract products , Created by a specific factory and mapped to a specific factory one by one .

Class diagram

 Insert picture description here

Advantages and disadvantages

advantage

  • When the system adds new products , You only need to add specific product categories and corresponding specific factories , No need to modify the original code . To satisfy the Opening and closing principle
  • Users can get products as long as they reach the name of the specific factory , There is no need to pay attention to the specific creation process of the product .

shortcoming

  • Each time a new product is added, there will be two more categories , In the long run, there will be many kinds , Increases the complexity of the system

Abstract factory pattern (AbstractFactory)

Concept

The simple factory mode and the factory method mode mentioned above only produce the same kind of products . For example, coffee factories only produce coffee , Only animals are kept in the pasture , Jiuyang soybean milk machine only makes soybean milk machine , Mobile phone stores only sell mobile phones . But in reality , The shopkeeper will not be so simple . For example, Huawei mobile phone store , You can't just sell mobile phones , He also buys computers 、 Television and even cars ( Right , Huawei also sells cars ).
That is to say, both simple factory mode and factory method mode can only produce Products of the same category ( Different coffee , Or different breeds of dogs ), And an abstract factory can Produce the same family , But different kinds of products ( We also produce mobile phones and computers , We also produce tops and pants )
About the same kind and kindred , For example, all electronic products belong to the same family , For example, computers and mobile phones belong to the same family . Then different types of a product are the same , For example, Huawei mate20 And Huawei p30.

Specific structure

The structure is actually the same as the factory method , But there are some subtle differences

  1. Abstract factory : Contains multiple methods for creating products , You can create different types of products ( Factory methods can only create one class )
  2. Specific factory : The implementation class of the abstract factory
  3. Abstract product : Define the specifications of the product ( It can be considered that the products defined by the same interface are of the same class )
  4. Specific products : Implementation classes of abstract products

Class diagram

 Insert picture description here

Advantages and disadvantages

  • advantage : Products in a product family only need one class . When there are multiple objects in a product family ( Cell phones and computers ) When designed to work together ( They are sold in Huawei stores ), It can ensure that the client only uses objects with one product family ( Customers can only buy Huawei products in Huawei stores , Those who can't buy apples ).
  • shortcoming : When a product family needs to add a new product ( There are many new methods in the abstract interface , Just like Huawei suddenly started selling cars ), All factory classes need to be modified .( All implementation classes must implement this method , We have to add the method of producing cars )

Use scenarios

Because there are many classes when the abstract factory is used , So it's not always suitable to use it .( For example, my coffee shop only sells coffee )

  1. When an object is created, it belongs to the same product family ( Mobile phones in Huawei stores 、 The computer 、 The headset )
  2. There are many product families in the system , However, users usually use one of them ( For example, most users use Apple Family bucket or Huawei family bucket )

Archetypal model

He uses an instance that has already been created as a template , Create a new object that is the same as the prototype object by copying .

structure

  1. Abstract prototype class : Specifies that the concrete prototype object must implement clone() Method .(Cloneable)
  2. Concrete prototype class : Implementing Abstract prototype classes clone() Method , He is a replicable object
  3. Access class : Use clone() Method to copy .

Class diagram and Implementation

There are two ways to copy the prototype pattern :
Shallow copy : Directly copied the object A Address to another object B. Because of the object A,B It refers to the same address, so it is modified B,A It's going to change .
Deep copy : Copied object A To another object B, There is no relationship between the two objects, pointing to different addresses . Modifying one will not affect the other .
I have implemented the following examples as shallow copy , More about shallow and deep copies , Look here
 Insert picture description here

Use scenarios

  • The creation of objects is complex , You can directly copy to quickly obtain objects
  • High performance and safety requirements

Builder pattern

  • The builder pattern separates the construction and presentation of a complex object , Let the same build process represent different products .
  • He separated the structure and assembly of the product parts . There were Builder and Director be responsible for , And can eventually generate complex objects . This pattern applies to : Generating an extremely complex object .
  • Due to the decoupling of construction and assembly , So the same structure , Different assemblies can generate different objects . Different structures , The same assembly , Different constructs can also generate different objects .( It can be understood as making hamburgers . The structure is the meat of hamburger , What kind of food is it , What is bread . Assembly is the order of placement , It can be bread with meat or bread with meat )
  • The builder pattern separates the product from the assembly process . The user only needs to specify the type of the complex object to get the object , There is no need to go to the creation details of specific objects

structure

  • Abstract builder (Builder): Specify the method that the builder needs to implement , It does not involve the creation of specific object parts
  • Specific builder : Abstract builder's implementation class , The way to achieve it , Responsible for the creation of specific object parts
  • product : The object to be created
  • commander (Director): Call the concrete builder to create the various parts of the complex object , And put them together in order .

Case class diagram

 Insert picture description here

Advantages and disadvantages

advantage :

  1. The builder pattern is very encapsulated , Can effectively respond to changes in product components , And the business logic is focused on Director Good medium stability .
  2. The client does not need to know the creation details of the product , Decouple the product itself from the product creation process , Make the same creation process possible to create different product objects .
  3. The product creation process can be finely controlled .
  4. Comply with opening and closing principle , It's easy to expand . If you want to have a new product, just build one more Builder The implementation class of is the concrete builder .
    shortcoming :
  5. If a new part needs to be added in the product update iteration , You need to modify a lot of specific builder classes .
  6. If the direct difference of products is too large, the builder model cannot be used

Use scenarios

The builder pattern is often used to create complex objects . The components of this object change frequently , But the combination process is relatively stable .

  1. Objects are complex , It's made up of several parts . But the construction sequence between components is stable
  2. The construction process and final representation of the product are independent

Comparison of similar creator patterns

Factory method model and builder model

Factory method model Pay attention to the creation of the whole object , and Builder pattern Pay attention to the process of component construction , Finally, a complex object is generated through the construction of components .
in other words Factory method model To create a computer is to create a computer directly , Builder pattern Just get it first cpu、gpu Then the motherboard will finally be assembled into a computer .

Abstract factory pattern and builder pattern

Abstract factory pattern It focuses on the production of a product family . He doesn't care about the build process , Just care about what products are produced by what factories .
builder Is to build the product according to the specified blueprint , His aim is to produce a new product by assembling parts .
If Abstract factory pattern It is an auto parts factory , that builder It's an automobile assembly plant . Parts produced by abstract factories , And then assembled by the builder .

原网站

版权声明
本文为[OldZhangYH]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206221758470575.html