Super detailed: summary of six common design patterns

Keywords: Java Mobile REST SpringBoot

Singleton mode

Simply put, in an application, there is only one instance object of a class. You can't go to new because the constructors are decorated by private. Generally, they get their instances through getInstance(). The return value of getInstance () is a reference to an object, not a new instance, so don't misunderstand it as multiple objects. It's easy to implement the singleton mode. Go to demo.

public class Singleton { 
    private static Singleton singleton; 
    private Singleton() { } 
    public static Singleton getInstance() {  
        if (singleton == null) { 
        singleton = new Singleton();
        } 
           return singleton;
    }
}

According to my habit, I wish I could write all the comments. I'm afraid you can't understand it, but this code is too simple, so I didn't write any comments. If you can't understand these lines of code, you can wash and sleep, and read my blog when you wake up.

The above is the most basic writing method, also known as lazy writing (thread is not safe). Next, I will publish several writing methods of singleton mode:

Lazy writing (thread safe)

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

Hungry Han style writing

public class Singleton {   
    private static Singleton instance = new Singleton();  
    private Singleton (){}    
    public static Singleton getInstance() {   
        return instance;    
    } 
}  

Static inner class

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

enumeration

public enum Singleton {    
    INSTANCE;   
    public void whateverMethod() { }  
}  

This method is advocated by Josh Bloch, author of Effective Java. It can not only avoid the problem of multithreading synchronization, but also prevent deserialization from re creating new objects. It's a very strong barrier. However, I think it's strange to write in this way because of the enum feature added in 1.5.

Double check lock

public class Singleton {  
    private volatile static Singleton singleton;   
    private Singleton (){}   
    public static Singleton getSingleton() { 
        if (singleton == null) {     
            synchronized (Singleton.class) {      
                if (singleton == null) {      
                    singleton = new Singleton();     
                }    
            }  
        }   
        return singleton;    
    }  
} 

Conclusion: I prefer static internal style and starved Chinese style. In fact, these two styles can cope with the vast majority of situations. Other writing methods can also be selected, mainly depending on business needs.

Observer mode

When the state of an object changes, all objects that depend on it are notified and updated automatically.

Observer pattern UML diagram

People who can't understand the picture come here with a small bench and give you a chestnut: suppose there are three people, Xiaomei (female, 28), Lao Wang and Lao Li. Xiaomei is very beautiful and coquettish. Lao Wang and Lao Li are two middle-aged male losers who always pay attention to Xiaomei's every move. One day, Xiaomei said, "my husband is not at home today. He's so bored. Laowang and Laoli heard this sentence. They were so happy that they rubbed against each other. After a while, Laowang rushed to Xiaomei's door and entered the door......... ... Pa Pa Pa Pa Pa Pa Pa - here, Xiaomei is the observed, Lao Wang and Lao Li are the observed, the observed sends a message, and then the observers process it accordingly, see the code:

public interface Person { 
//Lao Wang and Lao Li can receive messages from Xiaomei through this interface   
    void getMessage(String s);
}

This interface is equivalent to the phone numbers of Lao Wang and Lao Li. Xiaomei will call getMessage when she sends the notice. Calling is to call the interface. It doesn't matter if you don't understand it. Read it down first.

public class LaoWang implements Person { 
    private String name = "Lao Wang";  
    public LaoWang() {    }   
     @Override  
    public void getMessage(String s) {   
        System.out.println(name + "I received a call from Xiaomei, the content of which is:" + s);  
    } 
} 
    public class LaoLi implements Person {  
    private String name = "Lao Li"; 
    public LaoLi() {    }  
    @Override  
    public void getMessage(String s) {  
        System.out.println(name + "I received a call from Xiaomei, the content of which is:->" + s);  
    } 
}

The code is very simple. Let's take a look at Xiaomei's code:

public class XiaoMei {  
    List<Person> list = new ArrayList<Person>();   
    public XiaoMei(){     }   
    public void addPerson(Person person){   
        list.add(person); 
    }    
//Traverse the list and send your own notifications to all those who secretly love you  
    public void notifyPerson() {   
        for(Person person:list){     
            person.getMessage("I'm the only one at home today. Come here. Whoever comes first will get me.!");   
        }   
    }
}

Let's write a test class to see if the result is right.

public class Test {  
    public static void main(String[] args) {  
        XiaoMei xiao_mei = new XiaoMei();    
        LaoWang lao_wang = new LaoWang();    
        LaoLi lao_li = new LaoLi();   
        //Lao Wang and Lao Li have registered with Xiaomei.  
        xiao_mei.addPerson(lao_wang); 
        xiao_mei.addPerson(lao_li); 
        //Xiaomei sends a notice to Laowang and Laoli    
        xiao_mei.notifyPerson();   
    }
}

I took a screenshot of the results

Operation result

Perfect

Decorator mode

Further encapsulate the existing business logic to add additional functions, such as Java The I / O stream in uses the decorator mode. When users use it, they can assemble it at will to achieve the desired effect. For example, I want to eat a sandwich. First of all, I need a big sausage. I like to eat cream. Add a little cream on the sausage, put some vegetables on it, and then use two pieces of bread to sandwich it. It's a rich lunch, nutritious and healthy. (ps: I don't know where there are delicious sandwiches in Shanghai, please recommend ~) so how should we write the code? First of all, we need to write a Food class so that all other foods can inherit this class. Look at the code:

public class Food {   
    private String food_name;  
    public Food() {    }   
    public Food(String food_name) {   
        this.food_name = food_name; 
    }    
    public String make() {    
        return food_name;  
    };
}

The code is very simple, I won't explain it, and then we write several subclasses to inherit it:

//Bread type
public class Bread extends Food { 
    private Food basic_food;   
    public Bread(Food basic_food) {  
        this.basic_food = basic_food;  
    }   
    public String make() { 
        return basic_food.make()+"+bread"; 
    }
} 
//Creams
public class Cream extends Food {  
    private Food basic_food;  
    public Cream(Food basic_food) {  
        this.basic_food = basic_food;  
    }  
    public String make() {  
        return basic_food.make()+"+cream"; 
    }
} 
//Vegetables
public class Vegetable extends Food {
    private Food basic_food;   
    public Vegetable(Food basic_food) { 
        this.basic_food = basic_food; 
    }    
    public String make() { 
        return basic_food.make()+"+Vegetables"; 
    } 
}

These classes are almost the same. The constructor passes in a parameter of Food type, and then adds some logic to the make method. If you still can't understand why you write this, don't worry. Take a look at how my Test class is written, and you will see it.

public class Test { 
    public static void main(String[] args) { 
        Food food = new Bread(new Vegetable(new Cream(new Food("Sausage"))));                        System.out.println(food.make()); 
    }
}

See, layer by layer, we can see from the inside out: I have a new sausage in the innermost part, I have wrapped a layer of cream outside the sausage, and I have added a layer of vegetables outside the cream. What I put on the outermost part is bread, isn't it very vivid, ha ha... This design mode is almost the same as in real life, do you understand? Let's see the results

Operation result

A sandwich is ready

Adapter mode

Connect two completely different things together, like transformers in real life. Suppose that a mobile phone charger needs 20V, but the normal voltage is 220V. In this case, a transformer is needed to convert the voltage of 220V into 20V, so that the transformer connects 20V with the mobile phone.

public class Test { 
    public static void main(String[] args) {  
        Phone phone = new Phone();     
        VoltageAdapter adapter = new VoltageAdapter();   
        phone.setAdapter(adapter);     
        phone.charge();  
    }
} 
// Mobile phones
class Phone { 
    public static final int V = 220;
// Normal voltage 220v is a constant 
    private VoltageAdapter adapter; 
// Charge   
    public void charge() {   
        adapter.changeVoltage(); 
    }    
    public void setAdapter(VoltageAdapter adapter) { 
        this.adapter = adapter;   
    }
}
// Transformer
class VoltageAdapter {  
// Function of changing voltage  
    public void changeVoltage() {  
        System.out.println("Charging...");   
        System.out.println("Original voltage:" + Phone.V + "V");   
        System.out.println("Voltage after transformer conversion:" + (Phone.V - 200) + "V");  
    }
}

Factory mode

Simple factory pattern: an abstract interface, an implementation class of multiple abstract interfaces, and a factory class are used to instantiate the abstract interface.

// Abstract product class
abstract class Car { 
    public void run();  
    public void stop();
} 
// Concrete implementation class
class Benz implements Car {  
    public void run() { 
        System.out.println("Benz It's starting...");  
    }  
    public void stop() {  
        System.out.println("Benz Stop the car..."); 
    }
}
class Ford implements Car { 
    public void run() {   
        System.out.println("Ford It's starting...");   
    }    
    public void stop() { 
        System.out.println("Ford Stop the car.");  
    }
} 
// Factory class
class Factory {  
    public static Car getCarInstance(String type) {  
        Car c = null;   
    if ("Benz".equals(type)) {   
        c = new Benz();     
    }      
    if ("Ford".equals(type)) {  
        c = new Ford();     
    }     
        return c; 
    }
}
public class Test {  
    public static void main(String[] args) {  
        Car c = Factory.getCarInstance("Benz");   
    if (c != null) {   
        c.run();    
        c.stop();   
    } else {      
        System.out.println("I can't make such a car...");   
    }  
}
}

Factory method pattern: there are four roles: abstract factory pattern, concrete factory pattern, abstract product pattern and concrete product pattern. It is no longer a factory class to instantiate a specific product, but a subclass of an abstract factory to instantiate a product

// Abstract product role
    public interface Moveable {
        void run();
    } 
// Specific product roles
public class Plane implements Moveable {   
    @Override  
    public void run() {   
        System.out.println("plane....");  
    }
} 
public class Broom implements Moveable { 
    @Override 
    public void run() {  
        System.out.println("broom.....");
    }
} 
// Abstract factory
    public abstract class VehicleFactory { 
        abstract Moveable create();
    } 
// Specific factory
public class PlaneFactory extends VehicleFactory { 
    public Moveable create() {   
        return new Plane(); 
    }
} 
public class BroomFactory extends VehicleFactory { 
    public Moveable create() {    
        return new Broom();  
    }
} 
// Test class
public class Test {   
    public static void main(String[] args) {   
        VehicleFactory factory = new BroomFactory();   
        Moveable m = factory.create();  
        m.run(); 
    }
}

Abstract factory pattern: unlike factory method pattern, factory in factory method pattern only produces a single product, while factory in abstract factory pattern produces multiple products

/Abstract factory class
public abstract class AbstractFactory {  
    public abstract Vehicle createVehicle();  
    public abstract Weapon createWeapon();  
    public abstract Food createFood();
}
//Specific factory classes, where Food,Vehicle, and wepon are abstract classes.
public class DefaultFactory extends AbstractFactory{ 
    @Override  
    public Food createFood() {   
        return new Apple(); 
    }   
    @Override   
    public Vehicle createVehicle() { 
        return new Car();  
    }  
    @Override   
    public Weapon createWeapon() {  
        return new AK47();  
    }
}
//Test class
public class Test {  
    public static void main(String[] args) { 
        AbstractFactory f = new DefaultFactory();   
        Vehicle v = f.createVehicle();    
        v.run();   
        Weapon w = f.createWeapon(); 
        w.shoot();  
        Food a = f.createFood(); 
        a.printName();
    }
}

proxy mode

There are two kinds, static agent and dynamic agent. Let's start with static agent. I won't talk about many theoretical things. Even if I talk about them, you can't understand them. What real role, abstract role, agent role, delegation role... I can't understand the mess. When I was learning the agent mode, I went to the Internet to search for a lot of information and open the links. Basically, I gave you a lot of analysis about the roles and theories. It seems very hard. If you don't believe me, you can go and have a look. I can't understand what they are talking about. Let's not talk about it in vain, just use the examples in life. (Note: I'm not denying theoretical knowledge here. I just think that sometimes theoretical knowledge is obscure and difficult to understand. People who like to challenge go, you are here to learn knowledge, not to challenge.)
When we get to a certain age, we are going to get married. It is a very troublesome thing to get married (including those who are urged to marry by their parents). Rich families may look for a MC to preside over the wedding, which seems lively and foreign. Now that the business of the wedding company is coming, we just need to give money, and the wedding company will help us arrange a whole set of wedding process. The whole process is like this: family urging marriage - > the ecliptic of marriage agreed by both men and women's families today - > find a reliable wedding company - > hold the wedding ceremony at the appointed time - > marriage is over
How does the wedding company plan to arrange the wedding program? What will the wedding company do after the wedding? We have no idea... Don't worry, it's not a black intermediary. We just need to give money to others, who will do a good job for us. So, the wedding company here is equivalent to an agent role. Now you know what an agent role is.
For code implementation, see:

//Proxy interface
public interface ProxyInterface { 
//It's about marriage. If there are other things that need to be represented, such as eating, sleeping and going to the toilet, you can also write void mary();
//Proxy meal (own meal, let others eat it)
//void eat(); 
//Agency shit, own shit, let others pull it 
//void shit();
}

In a civilized society, I will not write about acting for eating and shit. It will hurt the social decency and make it clear.
OK, let's look at the code of the wedding company:

public class WeddingCompany implements ProxyInterface { 
    private ProxyInterface proxyInterface; 
    public WeddingCompany(ProxyInterface proxyInterface) {
        this.proxyInterface = proxyInterface;
    } 
    @Override
    public void marry() {  
        System.out.println("We're from the wedding company"); 
        System.out.println("We are preparing for our wedding"); 
        System.out.println("Program rehearsal..."); 
        System.out.println("Gift purchase..."); 
        System.out.println("Division of labor..."); 
        System.out.println("It's time to get married"); 
        proxyInterface.marry(); 
        System.out.println("After marriage, we need to do follow-up processing. You can go home and our company will do the rest."); 
    }
}

See? There are many things that wedding companies need to do. Let's look at the code of marriage family:

public class NormalHome implements ProxyInterface{ 
    @Override 
    public void marry() {  
        System.out.println("We're married~"); 
    }
}

It's already obvious that marriage families only need to get married, and the wedding company should take care of everything. All the things before and after are done by the wedding company. It's said that the wedding company is very profitable now. That's the reason. There are many jobs to do. Can we not make money?
Take a look at the test class code:

public class Test {
    public static void main(String[] args) { 
        ProxyInterface proxyInterface = new WeddingCompany(new NormalHome());                      proxyInterface.marry();
    }
}

The operation results are as follows:

In our expectation, the result is correct. This is static proxy. I don't want to say dynamic proxy. It's related to java reflection.


Focus on the public number [programmer's dream], focusing on Java, SpringBoot, SpringCloud, micro services, Docker and front end separation technology.

Posted by xzilla on Wed, 30 Oct 2019 03:33:22 -0700