Interview questions of design pattern
Program description DD 2021-07-09 02:55:11

What is design pattern

  • Design patterns , It's a set that's been used over and over again 、 Most people know that 、 Catalogued 、 Summary of code design experience . Design patterns are used for reusable code 、 Make code easier to understand 、 Ensure code reliability 、 Reusability of program .

Why study design patterns

  • Understand the source code : If you don't understand design patterns, look Jdk、Spring、SpringMVC、IO And so on , You'll be confused , You're going to have trouble walking
  • Look at the code of our predecessors : If you go to a company, it's all new projects for you to take over ? It's very likely to be a pick-up , Don't you use design patterns for the development of predecessors ?
  • Write your own ideal good code : I'm like this anyway , I will be very serious about my own projects , I treat him better than my girlfriend , Think of the project as your son

Design pattern classification

  • Create pattern , Five kinds in total : Factory method model 、 Abstract factory pattern The singleton pattern 、 Builder pattern 、 Archetypal model .
  • Structural mode , There are seven kinds of : Adapter pattern 、 Decorator mode 、 The proxy pattern 、 Appearance mode 、 Bridging mode 、 Portfolio model 、 The flyweight pattern .
  • Behavioral patterns , There are eleven kinds of : The strategy pattern 、 Template method pattern 、 Observer mode 、 Iterative subpattern 、 The chain of responsibility model 、 Command mode 、 Memo mode 、 The state pattern 、 Visitor mode 、 Intermediary model 、 Interpreter mode .

Six principles of design patterns

Open and closed principle (Open Close Principle)

  • Principle thinking : Try to solve the requirement change by extending the software entity , Instead of making changes by modifying existing code
  • describe : A software product is in its life cycle , Will change , Since change is a given fact , We should try to adapt to these changes in the design , To improve the stability and flexibility of the project .
  • advantage : The single principle tells us , Each class has its own responsibility , Richter's principle of substitution cannot destroy the system of succession .

Richter substitution principle (Liskov Substitution Principle)

  • Principle thinking : The base class used can use inherited subclasses anywhere , Perfect replacement base class .
  • Roughly meaning : A subclass can extend the functionality of a parent class , But you cannot change the original functionality of the parent class . Subclasses can implement the abstract methods of the parent class , But you cannot override non-abstract methods of a parent class , Subclasses can add their own unique methods .
  • advantage : Increase the robustness of the program , Even with the addition of subclasses , The original subclass can continue to run , They don't influence each other .

Dependence Inversion Principle (Dependence Inversion Principle)

  • The core idea of dependency inversion principle is interface oriented programming .
  • The dependency inversion principle requires us to pass parameters in the program code or in the association relationship , Try to refer to high-level abstract classes ,
  • This is the foundation of the open and closed principle , The specific content is : Programming the interface , It depends on the abstract and not on the concrete .

Interface isolation principle (Interface Segregation Principle)

  • This principle means : Use multiple isolated interfaces , Better than using a single interface . It also means reducing the coupling between classes , From here we can see that , In fact, design pattern is a software design idea , Start with a large software architecture , For the convenience of upgrading and maintenance . So many times in the above : Reduce dependence , To reduce the coupling .
  • for example : Interface between payment class and order class , We need to turn these two types of interfaces into two isolated interfaces

Dimitar's law ( Least known principle )(Demeter Principle)

  • Principle thinking : One object should know as little as possible about other objects , Inter class decoupling
  • It means that a class should minimize its dependence on other objects , The principle is low coupling , High cohesion , Only make the coupling between modules as low as possible , To improve the reuse rate of code .
  • advantage : Low coupling , High cohesion .

Principle of single responsibility (Principle of single responsibility)

  • Principle thinking : One method is only responsible for one thing .
  • describe : The single responsibility principle is simple , One way A class has only one responsibility , Procedure changes for each responsibility , Does not affect other procedures . This is common sense , Almost all programmers follow this principle .
  • advantage : Reduce the coupling between classes , Improve readability , Increase maintainability and scalability , Reduce the risk of variability .

The singleton pattern

1. What is a single example

  • Ensure that a class has only one instance , And provide an access to the global access point

2. In those places, singleton patterns are used

  1. Counters for websites , In general, it is also implemented in the single instance mode , Otherwise, it is difficult to synchronize .
  2. Application log application , It's usually implemented in singleton mode , Only one instance can be operated , Otherwise, the content is not easy to be displayed .
  3. The design of multithreaded thread pool generally adopts the single instance mode , Because the thread pool should be convenient to control the threads in the pool
  4. Windows Of ( Task manager ) It's a typical one-off model , He can't open two
  5. windows Of ( The recycle bin ) It is also a typical single application . During the operation of the whole system , The recycle bin maintains only one instance .

3. Advantages and disadvantages of single case

advantage :

  1. In singleton mode , Single instance of an activity has only one instance , All instantiations of a singleton class result in the same instance . This prevents other objects from instantiating themselves , Ensure that all objects access an instance
  2. The singleton mode has certain scalability , Class to control the instantiation process , Class has corresponding scalability in changing the instantiation process .
  3. Provides controlled access to unique instances .
  4. Because there is only one object in system memory , Therefore, system resources can be saved , When you need to create and destroy objects frequently, singleton mode can undoubtedly improve the performance of the system .
  5. Allows a variable number of instances .
  6. Avoid multiple use of shared resources .

shortcoming :

  1. Not applicable to changed objects , If objects of the same type always change in different use case scenarios , Single instance will cause data error , Can't save each other's states .
  2. Because there is no abstraction layer in the simple interest model , Therefore, the extension of singleton classes is very difficult .
  3. Singleton classes are overloaded , To a certain extent “ Principle of single responsibility ”.
  4. Abuse of single case will bring some negative problems , For example, in order to save resources, the database connection pool object is designed as a single instance class , May cause too many programs sharing connection pool objects to overflow connection pool ; If the instantiated object is not used for a long time , The system will be recycled as garbage , This will result in the loss of object state .

4. Note for singleton mode use :

  1. You cannot use reflection mode to create a single instance , Otherwise, a new object will be instantiated
  2. Pay attention to thread safety when using lazy singleton mode
  3. Both hungry singleton pattern and lazy singleton pattern construction methods are private , So it can't be inherited , Some singleton patterns can be inherited ( Such as registration mode )

5. Single example to prevent reflection vulnerability attack

private static boolean flag = false;

private Singleton() {

if (flag == false) {
flag = !flag;
} else {
throw new RuntimeException(" The singleton pattern is violated !");
}
}

public static void main(String[] args) {

}

6. How to choose a single instance creation method

  • If you don't need to delay loading the singleton , You can use enumeration or starvation , Comparatively speaking, enumeration is better than starvation . If you need to delay loading , You can use static inner classes or lazy , Relatively speaking, static inner class is better than lazy Korean . It's better to use the hungry man style

7. How to create a single instance

( Mainly use lazy and lazy style )

  1. Hungry Chinese style : Class initialization , The object will be loaded immediately , Threads are inherently safe , High call efficiency .
  2. Slacker type : Class initialization , The object will not be initialized , This object is only created when it really needs to be used , Lazy loading function .
  3. Static internal way : It combines the advantages of lazy and hungry , Only when the object is really needed can it be loaded , Loading classes is thread safe .
  4. Enumerate singletons : Use enumeration to implement singleton pattern advantage : Implement a simple 、 High call efficiency , Enumeration itself is a singleton , from jvm Fundamental guarantee ! Avoid loopholes through reflection and deserialization , Disadvantages no delay in loading .
  5. Double detection lock mode ( because JVM The reason for the essential reordering , May be initialized multiple times , It is not recommended to use )

1. Hungry Chinese style

  1. Hungry Chinese style : Class initialization , The object will be loaded immediately , Threads are inherently safe , High call efficiency .
package com.lijie;

// Hungry Chinese style
public class Demo1 {

// Class initialization , The object will be loaded immediately , Thread safety , High call efficiency
private static Demo1 demo1 = new Demo1();

private Demo1() {
System.out.println(" private Demo1 Construct parameter initialization ");
}

public static Demo1 getInstance() {
return demo1;
}

public static void main(String[] args) {
Demo1 s1 = Demo1.getInstance();
Demo1 s2 = Demo1.getInstance();
System.out.println(s1 == s2);
}
}

2. Slacker type

  1. Slacker type : Class initialization , The object will not be initialized , This object is only created when it really needs to be used , Lazy loading function .
package com.lijie;

// Slacker type
public class Demo2 {

// Class initialization , The object will not be initialized , This object is only created when it really needs to be used .
private static Demo2 demo2;

private Demo2() {
System.out.println(" private Demo2 Construct parameter initialization ");
}

public synchronized static Demo2 getInstance() {
if (demo2 == null) {
demo2 = new Demo2();
}
return demo2;
}

public static void main(String[] args) {
Demo2 s1 = Demo2.getInstance();
Demo2 s2 = Demo2.getInstance();
System.out.println(s1 == s2);
}
}

3. Static inner class

  1. Static internal way : It combines the advantages of lazy and hungry , Only when the object is really needed can it be loaded , Loading classes is thread safe .
package com.lijie;

// Static inner class mode
public class Demo3 {

private Demo3() {
System.out.println(" private Demo3 Construct parameter initialization ");
}

public static class SingletonClassInstance {
private static final Demo3 DEMO_3 = new Demo3();
}

// Method is not synchronized
public static Demo3 getInstance() {
return SingletonClassInstance.DEMO_3;
}

public static void main(String[] args) {
Demo3 s1 = Demo3.getInstance();
Demo3 s2 = Demo3.getInstance();
System.out.println(s1 == s2);
}
}

4. Enumerating singletons

  1. Enumerate singletons : Use enumeration to implement singleton pattern advantage : Implement a simple 、 High call efficiency , Enumeration itself is a singleton , from jvm Fundamental guarantee ! Avoid loopholes through reflection and deserialization , Disadvantages no delay in loading .
package com.lijie;

// Use enumeration to implement singleton pattern advantage : Implement a simple 、 Enumeration itself is a singleton , from jvm Fundamental guarantee ! Avoid loopholes through reflection and deserialization Disadvantages no delay in loading
public class Demo4 {

public static Demo4 getInstance() {
return Demo.INSTANCE.getInstance();
}

public static void main(String[] args) {
Demo4 s1 = Demo4.getInstance();
Demo4 s2 = Demo4.getInstance();
System.out.println(s1 == s2);
}

// Define enumeration
private static enum Demo {
INSTANCE;
// Enumeration elements are singletons
private Demo4 demo4;

private Demo() {
System.out.println(" enumeration Demo Private construction parameters ");
demo4 = new Demo4();
}

public Demo4 getInstance() {
return demo4;
}
}
}

5. Double detection lock mode

  1. Double detection lock mode ( because JVM The reason for the essential reordering , May be initialized multiple times , It is not recommended to use )
package com.lijie;

// Double detection lock mode
public class Demo5 {

private static Demo5 demo5;

private Demo5() {
System.out.println(" private Demo4 Construct parameter initialization ");
}

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

public static void main(String[] args) {
Demo5 s1 = Demo5.getInstance();
Demo5 s2 = Demo5.getInstance();
System.out.println(s1 == s2);
}
}

Factory mode

1. What is factory mode

  • It provides the best way to create objects . In factory mode , We don't expose the creation logic to the client when we create the object , And by using a common interface to point to newly created objects . Separation of the creator and the caller , The factory model is divided into simple factories 、 Factory method 、 Abstract factory pattern

2. Benefits of the factory model

  • Factory pattern is the most commonly used instantiation object pattern , It's a factory approach new A mode of operation .
  • Using factory mode can reduce the coupling of programs , It provides great convenience for later maintenance and modification .
  • Implementation class will be selected 、 Create object unified management and control . To decouple the caller from our implementation class .

3. Why learn factory design patterns

  • I don't know if you've asked the source code in your interview , You know, Spring Source code of ,MyBatis Source code of , And so on. If you want to learn the source code of many frameworks , Or you want to develop your own framework , You have to master the design pattern first ( The factory design pattern uses a very, very wide range of )

4.Spring Factory design patterns in development

1.Spring IOC

  • seen Spring The source code knows , stay Spring IOC Container to create bean The process is to use the factory design pattern
  • Spring Whether through xml Configuration is created by configuration class or annotation bean, Most are created through simple factories .
  • When the container gets beanName and class After the type , Dynamically create a specific object through reflection , Finally, put the created object in Map in .

2. Why? Spring IOC To create using factory design patterns Bean Well

  • In actual development , If we A Object call B,B call C,C call D If we do, the coupling of our program will be higher .( Coupling is roughly divided into dependencies between classes , Dependencies between methods .)
  • In the three-tier architecture programming of a long time ago , The control layer calls the business layer , When the business layer calls the data access layer , It's all direct new object , The coupling is greatly improved , Code duplication is high , Objects are flying all over the world
  • To avoid that ,Spring Use factory mode programming , Write a factory , Created by the factory Bean, In the future, if we want the object, we can directly manage the factory , We're not in charge of the rest .Spring IOC There is a static one in the factory of the container Map aggregate , This is to make the factory conform to the singleton design pattern , That is, each object is produced only once , After the object is produced, it is stored in Map Collection , Ensure that the instance will not repeat, affect the efficiency of the program .

5. Factory pattern classification

  • The factory model is divided into simple factories 、 Factory method 、 Abstract factory pattern
 Simple factory : Used to produce any product in the same hierarchy .( We don't support expanding and adding products )
Factory method : Used to produce fixed products in the same hierarchy .( Support to expand and increase products )
Abstract factory : All the products used to produce different product families .( We don't support expanding and adding products ; Support to add product families )

I'm going to use the code to demonstrate :

5.1 Simple factory model

What is the simple factory model

  • The simple factory model is equivalent to having all kinds of products in a factory , Create in a class , The customer does not need to know the name of the specific product , You only need to know the parameters corresponding to the product class . But the responsibility of the factory is too heavy , And when there are too many types, it is not conducive to the extension maintenance of the system .

Code demonstration :

  1. Create a factory
package com.lijie;

public interface Car {
public void run();
}
  1. Create a factory product ( BMW )
package com.lijie;

public class Bmw implements Car {
public void run() {
System.out.println(" I'm BMW ...");
}
}
  1. Create another product ( audi )
package com.lijie;

public class AoDi implements Car {
public void run() {
System.out.println(" I'm Audi ..");
}
}
  1. Create core factory classes , It's up to him to decide which product to call
package com.lijie;

public class CarFactory {

public static Car createCar(String name) {
if ("".equals(name)) {
return null;
}
if(name.equals(" audi ")){
return new AoDi();
}
if(name.equals(" BMW ")){
return new Bmw();
}
return null;
}
}
  1. Demonstrate a concrete example of creating a factory
package com.lijie;

public class Client01 {

public static void main(String[] args) {
Car aodi =CarFactory.createCar(" audi ");
Car bmw =CarFactory.createCar(" BMW ");
aodi.run();
bmw.run();
}
}

Advantages of single plant / shortcoming

  • advantage : The simple factory model can be based on the information given by the outside world , Determines which concrete class object should be created . There is a clear distinction between their duties and powers , It is beneficial to the optimization of the whole software architecture .
  • shortcoming : It's obvious that the factory class concentrates the creation logic of all instances , Easy to violate GRASPR The principle of high cohesive responsibility distribution

5.2 Factory method model

What is the factory method pattern

  • Factory method model Factory Method, Also known as polymorphic factory pattern . In the factory method pattern , The core factory class is no longer responsible for all product creation , Instead, the specific creation is left to the subclass to do . The core class becomes an abstract factory role , Only responsible for giving the interface that the specific factory subclass must implement , Without touching the details of which product class should be instantiated

Code demonstration :

  1. Create a factory
package com.lijie;

public interface Car {
public void run();
}
  1. Create factory method call interface ( All products need new We must inherit him to realize the method )
package com.lijie;

public interface CarFactory {

Car createCar();

}
  1. Create a factory product ( audi )
package com.lijie;

public class AoDi implements Car {
public void run() {
System.out.println(" I'm Audi ..");
}
}
  1. Create a factory, another product ( BMW )
package com.lijie;

public class Bmw implements Car {
public void run() {
System.out.println(" I'm BMW ...");
}
}
  1. Create an instance of the factory method call interface ( audi )
package com.lijie;

public class AoDiFactory implements CarFactory {

public Car createCar() {

return new AoDi();
}
}
  1. Create an instance of the factory method call interface ( BMW )
package com.lijie;

public class BmwFactory implements CarFactory {

public Car createCar() {

return new Bmw();
}

}
  1. Demonstrate a concrete example of creating a factory
package com.lijie;

public class Client {

public static void main(String[] args) {
Car aodi = new AoDiFactory().createCar();
Car jili = new BmwFactory().createCar();
aodi.run();
jili.run();
}
}

5.3 Abstract factory pattern

What is abstract factory pattern

  • The abstract factory is simply the factory of the factory , Abstract factories can create concrete factories , Specific products are produced by specific factories .null_3.png Code demonstration :
  1. Create the first sub factory , And implementation classes
package com.lijie;

// automobile
public interface Car {
void run();
}

class CarA implements Car{

public void run() {
System.out.println(" BMW ");
}

}
class CarB implements Car{

public void run() {
System.out.println(" Mobai ");
}

}
  1. Create a second sub factory , And implementation classes
package com.lijie;

// The engine
public interface Engine {

void run();

}

class EngineA implements Engine {

public void run() {
System.out.println(" It turns fast !");
}

}

class EngineB implements Engine {

public void run() {
System.out.println(" It turns slowly !");
}

}
  1. Create a general plant , And implementation classes ( It's up to the implementation class of the master factory to call that instance of that factory )
package com.lijie;

public interface TotalFactory {
// Create a car
Car createChair();
// Create engine
Engine createEngine();
}

// Total factory implementation class , It's up to him to call that instance of which factory
class TotalFactoryReally implements TotalFactory {

public Engine createEngine() {

return new EngineA();
}

public Car createChair() {

return new CarA();
}
}
  1. Run the test
package com.lijie;

public class Test {

public static void main(String[] args) {
TotalFactory totalFactory2 = new TotalFactoryReally();
Car car = totalFactory2.createChair();
car.run();

TotalFactory totalFactory = new TotalFactoryReally();
Engine engine = totalFactory.createEngine();
engine.run();
}
}

The proxy pattern

1. What is agent mode

  • Control the access of objects through agents , Before this object calls a method 、 After calling the method, handle / Add new features .( That is to say AO Of P Microimplementation )
  • The agent does not modify the original code or even the original business process , Cut into new code directly in the business process , Add new features , It's the same with Spring Of ( Section oriented programming ) Very similar

2. Proxy mode application scenario

  • Spring AOP、 Log printing 、 exception handling 、 Transaction control 、 Authority control, etc

3. Classification of agents

  • Static proxy ( Define proxy classes statically )
  • A dynamic proxy ( Generate agent classes dynamically , Also known as Jdk With dynamic agent )
  • Cglib 、javaassist( Bytecode operation Library )

4. The difference between the three agents

  1. Static proxy : Simple proxy model , It is the theoretical basis of dynamic agent . Commonly used in proxy mode
  2. jdk A dynamic proxy : Use reflection to complete the proxy . You need a top-level interface to use , It's common to see mybatis Of mapper Files are agents .
  3. cglib A dynamic proxy : Also use reflection to complete the proxy , You can directly proxy classes (jdk Dynamic proxy doesn't work ), Using bytecode Technology , Not right final Class to inherit .( Import required jar package )

5. Demonstrate three proxies in code

5.1. Static proxy

What is a static agent

  • The source code of the agent class created by the programmer or generated by the tool , Recompile agent class . Static means that the bytecode file of the agent class already exists before the program runs , The relationship between the agent class and the delegate class is determined before running .

Code demonstration :

  • I have a piece of code like this :( How can it be done without modification UserDao How about opening and closing transactions in the case of interface class )
package com.lijie;

// Interface class
public class UserDao{
public void save() {
System.out.println(" How to save data ");
}
}

package com.lijie;

// Run test class
public class Test{
public static void main(String[] args) {
UserDao userDao = new UserDao();
userDao.save();
}
}

Modify the code , Add proxy class

package com.lijie;

// proxy class
public class UserDaoProxy extends UserDao {
private UserDao userDao;

public UserDaoProxy(UserDao userDao) {
this.userDao = userDao;
}

public void save() {
System.out.println(" Opening things ...");
userDao.save();
System.out.println(" Close things ...");
}

}

// Add static proxy test class
public class Test{
public static void main(String[] args) {
UserDao userDao = new UserDao();
UserDaoProxy userDaoProxy = new UserDaoProxy(userDao);
userDaoProxy.save();
}
}
  • shortcoming : Every object that needs a proxy needs to write its own proxy , Very uncomfortable ,
  • advantage : But the proxy can be implemented in the way of real object or interface

2.2. A dynamic proxy

What is dynamic agent

  • Dynamic agents are also called ,JDK agent 、 The interface agent .
  • Object of dynamic proxy , It's using JDK Of API, Dynamically build proxy objects in memory ( The proxy class is generated dynamically according to the interface of the proxy class file , And load the running process ), This is called dynamic proxy
package com.lijie;

// Interface
public interface UserDao {
void save();
}

package com.lijie;

// Interface implementation class
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println(" How to save data ");
}
}
  • // Here's the proxy class , reusable , Unlike static agents, you need to write your own agents repeatedly
package com.lijie;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// Every time a dynamic proxy class object is generated , Realized InvocationHandler Interface call handler object
public class InvocationHandlerImpl implements InvocationHandler {

// This is actually a business implementation class object , Used to call specific business methods
private Object target;

// Pass in the target object through the constructor
public InvocationHandlerImpl(Object target) {
this.target = target;
}

// The agent method that the dynamic agent actually runs
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(" Call to start processing ");
// below invoke() The method is to create objects in a reflective way , The first parameter is the object to create , The second is the parameters that make up the method , The second parameter determines which construction method to use to create the object
Object result = method.invoke(target, args);
System.out.println(" Call end processing ");
return result;
}
}
  • // Using dynamic proxies, using proxy methods
package com.lijie;

import java.lang.reflect.Proxy;

public class Test {
public static void main(String[] args) {
// Proxied object
UserDao userDaoImpl = new UserDaoImpl();
InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDaoImpl);

// Class loader
ClassLoader loader = userDaoImpl.getClass().getClassLoader();
Class<?>[] interfaces = userDaoImpl.getClass().getInterfaces();

// Main loader 、 A set of interfaces and calls to handle dynamic proxy instances
UserDao newProxyInstance = (UserDao) Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl);
newProxyInstance.save();
}
}
  • shortcoming : Must be interface oriented , The target business class must implement the interface
  • advantage : Don't worry about proxy classes , You only need to specify which object to delegate at run time

5.3.CGLIB A dynamic proxy

CGLIB Principle of dynamic agent :

  • utilize asm Open source package , For the proxy object class class File load in , By modifying its bytecode generation subclass to handle .

What is? CGLIB A dynamic proxy

  • CGLIB Dynamic proxy sum jdk It's like an agent , Use reflection to complete the proxy , The difference is that it can directly proxy classes (jdk Dynamic proxy doesn't work , He has to target the business class and implement the interface ),CGLIB The underlying dynamic proxy uses bytecode technology ,CGLIB Dynamic proxies cannot be used to final Class to inherit .(CGLIB Dynamic agents need to import jar package )

Code demonstration :

package com.lijie;

// Interface
public interface UserDao {
void save();
}

package com.lijie;

// Interface implementation class
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println(" How to save data ");
}
}

package com.lijie;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

// Agent main class
public class CglibProxy implements MethodInterceptor {
private Object targetObject;
// The type of goal here is Object, You can accept any parameter as the proxy class , Dynamic agent is realized
public Object getInstance(Object target) {
// Set the classes that need to create subclasses
this.targetObject = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}

// The actual method of agency
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println(" Opening things ");
Object result = proxy.invoke(targetObject, args);
System.out.println(" Close things ");
// Return proxy object
return result;
}
}


package com.lijie;

// test CGLIB A dynamic proxy
public class Test {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
UserDao userDao = (UserDao) cglibProxy.getInstance(new UserDaoImpl());
userDao.save();
}
}

Builder pattern

1. What is builder mode

  • Builder pattern : It is to separate the construction of a complex object from its representation , So that the same build process can be created in different ways .
  • The factory class pattern provides a product that creates a single class
  • And the builder model is to put all kinds of products together for management , For products with different properties

The builder pattern usually includes the following roles :

  1. uilder: Give an abstract interface , To standardize the construction of various components of the product object . This interface specifies which parts of the complex object are to be created , It does not involve the creation of specific object parts .
  2. ConcreteBuilder: Realization Builder Interface , For different business logic , Materialize the creation of parts of complex objects . After the completion of the construction process , Provide examples of products .
  3. Director: Call specific builders to create parts of complex objects , No product specific information is involved in the mentor , It is only responsible for ensuring that all parts of the object are created completely or in a certain order .
  4. Product: Complex object to create .

2. Usage scenarios of builder mode

Use scenarios :

  1. The objects that need to be generated have complex internal structures .
  2. The internal properties of the objects that need to be generated depend on each other .
  • The difference from the factory model is : Builder mode pays more attention to the order of parts assembly .
  • JAVA Medium StringBuilder It's the builder model that creates , He put a single character of char Arrays together
  • Spring It's not builder mode , The operations it provides should be some operations on the string itself , Instead of creating or changing a string .

3. Code case

  1. Create an equipment object Arms
package com.lijie;

// Equipment
public class Arms {
// Helmet
private String helmet;
// Armor
private String armor;
// weapons
private String weapon;

// Omit Git and Set Method ...........
}
  1. establish Builder Interface ( Give an abstract interface , To standardize the construction of various components of the product object , This interface is just a specification )
package com.lijie;

public interface PersonBuilder {

void builderHelmetMurder();

void builderArmorMurder();

void builderWeaponMurder();

void builderHelmetYanLong();

void builderArmorYanLong();

void builderWeaponYanLong();

Arms BuilderArms(); // assemble
}
  1. establish Builder Implementation class ( This class mainly implements which parts of complex object creation need what attributes )
package com.lijie;

public class ArmsBuilder implements PersonBuilder {
private Arms arms;

// Create a Arms example , Used to invoke set Method
public ArmsBuilder() {
arms = new Arms();
}

public void builderHelmetMurder() {
arms.setHelmet(" Lethal Helmets ");
}

public void builderArmorMurder() {
arms.setArmor(" Lethal armor ");
}

public void builderWeaponMurder() {
arms.setWeapon(" Lethal sword ");
}

public void builderHelmetYanLong() {
arms.setHelmet(" Dragon helmet ");
}

public void builderArmorYanLong() {
arms.setArmor(" Dragon Armor ");
}

public void builderWeaponYanLong() {
arms.setWeapon(" Yanlong sword ");
}

public Arms BuilderArms() {
return arms;
}
}
  1. Director( Call specific builders to create parts of complex objects , No product specific information is involved in the mentor , It is only responsible for ensuring that all parts of the object are created completely or in a certain order )
package com.lijie;

public class PersonDirector {

// assemble
public Arms constructPerson(PersonBuilder pb) {
pb.builderHelmetYanLong();
pb.builderArmorMurder();
pb.builderWeaponMurder();
return pb.BuilderArms();
}

// Test here
public static void main(String[] args) {
PersonDirector pb = new PersonDirector();
Arms arms = pb.constructPerson(new ArmsBuilder());
System.out.println(arms.getHelmet());
System.out.println(arms.getArmor());
System.out.println(arms.getWeapon());
}
}

Template method pattern

1. What is the template method

  • Template method pattern : Define the algorithm skeleton of an operation ( Parent class ), Instead, defer some steps to subclasses . The template method allows subclasses to redefine an algorithm without changing its structure

2. When to use the template method

  • When doing something , The whole process is very fixed , But what? . It's a small part of it that needs to change , In this case, you can use the template method pattern , Abstract out the changeable parts , For subclasses to implement .

3. In the actual development, the template method is used in the application scenario

  • In fact, many frameworks use template method patterns
  • for example : Encapsulation of database access 、Junit unit testing 、servlet About China doGet/doPost Method calls and so on

4. The template method in real life

for example :

  1. Go to the restaurant , The restaurant provides us with a template, which is : Look at the menu , May I take your order? , having dinner , payment , Leave ( here “ Ordering and paying ” It's indeterminate. It's done by subclasses , The rest is a template .)

5. Code implementation template method pattern

  1. Define a template first . Put the order and payment in the template , Let the subclass implement .
package com.lijie;

// Template method
public abstract class RestaurantTemplate {

// 1. Look at the menu
public void menu() {
System.out.println(" Look at the menu ");
}

// 2. Order business
abstract void spotMenu();

// 3. Dining business
public void havingDinner(){ System.out.println(" having dinner "); }

// 3. Payment business
abstract void payment();

// 3. Leave
public void GoR() { System.out.println(" Leave "); }

// Template general structure
public void process(){
menu();
spotMenu();
havingDinner();
payment();
GoR();
}
}
  1. Specific template method subclasses 1
package com.lijie;

public class RestaurantGinsengImpl extends RestaurantTemplate {

void spotMenu() {
System.out.println(" Ginseng ");
}

void payment() {
System.out.println("5 fast ");
}
}
  1. Specific template method subclasses 2
package com.lijie;

public class RestaurantLobsterImpl extends RestaurantTemplate {

void spotMenu() {
System.out.println(" lobster ");
}

void payment() {
System.out.println("50 block ");
}
}
  1. Client side test
package com.lijie;

public class Client {

public static void main(String[] args) {
// Call the first template instance
RestaurantTemplate restaurantTemplate = new RestaurantGinsengImpl();
restaurantTemplate.process();
}
}

Appearance mode

1. What is the appearance mode

  • Appearance mode : It's also called facade mode , Hide the complexity of the system , And provides an interface for the client to access the system .
  • It adds an interface to an existing system , Use this interface to hide the complexity of the actual system .
  • Use appearance mode , It looks like an interface on the outside , In fact, many complex interfaces have been implemented inside

2. Appearance pattern example

  • After the user has registered , You need to call the alisms interface 、 Mail interface 、 Wechat push interface .
  1. Create an alisms interface
package com.lijie;

// Ali text message
public interface AliSmsService {
void sendSms();
}

package com.lijie;

public class AliSmsServiceImpl implements AliSmsService {

public void sendSms() {
System.out.println(" Ali text message ");
}

}
  1. Create a mail interface
package com.lijie;

// Send a mail message
public interface EamilSmsService {
void sendSms();
}

package com.lijie;

public class EamilSmsServiceImpl implements EamilSmsService{
public void sendSms() {
System.out.println(" Send a mail message ");
}
}
  1. Create wechat push interface
package com.lijie;

// Wechat message push
public interface WeiXinSmsService {
void sendSms();
}

package com.lijie;

public class WeiXinSmsServiceImpl implements WeiXinSmsService {
public void sendSms() {
System.out.println(" Send wechat message push ");
}
}
  1. Create a facade ( The facade looks simple to use , Complicated things and being packaged by the facade )
package com.lijie;

public class Computer {
AliSmsService aliSmsService;
EamilSmsService eamilSmsService;
WeiXinSmsService weiXinSmsService;

public Computer() {
aliSmsService = new AliSmsServiceImpl();
eamilSmsService = new EamilSmsServiceImpl();
weiXinSmsService = new WeiXinSmsServiceImpl();
}

// Just call it
public void sendMsg() {
aliSmsService.sendSms();
eamilSmsService.sendSms();
weiXinSmsService.sendSms();
}
}
  1. Start the test
package com.lijie;

public class Client {

public static void main(String[] args) {
// The normal model needs to be like this
AliSmsService aliSmsService = new AliSmsServiceImpl();
EamilSmsService eamilSmsService = new EamilSmsServiceImpl();
WeiXinSmsService weiXinSmsService = new WeiXinSmsServiceImpl();
aliSmsService.sendSms();
eamilSmsService.sendSms();
weiXinSmsService.sendSms();

// Using appearance patterns to simplify methods
new Computer().sendMsg();
}
}

Archetypal model

1. What is a prototype pattern

  • Prototyping is simply cloning
  • The prototype shows that there is a template instance , This prototype is customizable . Prototype patterns are often used to create complex or time-consuming instances , Because in this case , Copying an existing instance can make the program run more efficiently .

2. Application scenario of prototype mode

  1. Class initialization needs to digest a lot of resources , This resource includes data 、 Hardware resources, etc . At this time, we can avoid the consumption by copying the prototype .
  2. adopt new The generated object needs very complicated data preparation or permission , You can use prototype mode .
  3. An object needs to be provided for other objects to access , And each caller may need to change its value , Consider using prototype mode to copy multiple objects for use by callers , Protective copy .
 We Spring Many examples in the framework are the use of prototypes .

3. How prototype patterns are used

  1. Realization Cloneable Interface . stay java There is a language Cloneable Interface , It has only one function , It is to inform the virtual machine at run time that it can be used safely on the class implementing this interface clone Method . stay java In the virtual machine , Only classes that implement this interface can be copied , Otherwise, it will throw CloneNotSupportedException abnormal .
  2. rewrite Object Class clone Method .Java in , The parent of all classes is Object class ,Object There is one in the class clone Method , The function is to return a copy of the object , But its scope is protected Type of , A normal class cannot call , therefore Prototype Class needs to clone The scope of the method is modified to public type .

3.1 The prototype mode is divided into shallow replication and deep replication

  1. ( A shallow copy ) It's just copying basic types of data , Reference type data , Just a copy of the reference address .
  2. ( Deep copy ) A new memory address has been opened up in the computer to store the copied objects .

4. Code demonstration

  1. establish User class
package com.lijie;

import java.util.ArrayList;

public class User implements Cloneable {
private String name;
private String password;
private ArrayList<String> phones;

protected User clone() {
try {
User user = (User) super.clone();
// a key , If you want to copy with reference types , You need to add the next code , If not, the reference address is copied
user.phones = (ArrayList<String>) this.phones.clone();// Set up deep copy
return user;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}

// Omit all attributes Git Set Method ......
}
  1. Test replication
package com.lijie;

import java.util.ArrayList;

public class Client {
public static void main(String[] args) {
// establish User Prototype object
User user = new User();
user.setName(" Li San ");
user.setPassword("123456");
ArrayList<String> phones = new ArrayList<>();
phones.add("17674553302");
user.setPhones(phones);

//copy One user object , And the properties of the object
User user2 = user.clone();
user2.setPassword("654321");

// See if two objects are one
System.out.println(user == user2);

// View the property content
System.out.println(user.getName() + " | " + user2.getName());
System.out.println(user.getPassword() + " | " + user2.getPassword());
// See for reference type copy
System.out.println(user.getPhones() == user2.getPhones());
}
}
  1. If you don't need deep replication , You need to remove User Medium
// The default reference type is shallow copy , This is set up for deep copy 
user.phones = (ArrayList<String>) this.phones.clone();

The strategy pattern

1. What is the strategic model

  • A series of algorithms are defined or Logic or Operations in the same sense , And each algorithm 、 Logic 、 The operation is encapsulated , And so that they can replace each other .( In fact, the strategic model Java It's very, very widely used in )
  • I think it's mainly for simplify if…else Complex and difficult to maintain .

2. Application scenario of strategy mode

  • The policy pattern is intended for a set of algorithms or logic , Encapsulate each algorithm or logic into a separate class with a common interface , So that they can replace each other .
  1. for example : I'm going to do three strategies with different discount strength for different members , Junior member , Intermediate members , Senior member ( Three different calculations ).
  2. for example : I want a payment module , I want to have wechat payment 、 Alipay pay 、 UnionPay payment, etc

3. The advantages and disadvantages of the strategy model

  • advantage : 1、 The algorithm can be switched freely . 2、 Avoid using multiple conditional judgments . 3、 Very scalable .
  • shortcoming : 1、 The number of strategy classes will increase . 2、 All policy classes need to be exposed .

4. Code demonstration

  • The analog payment module has wechat payment 、 Alipay pay 、 UnionPay payment
  1. Define abstract public methods
package com.lijie;

// The strategy pattern Define abstract methods All support public interfaces
abstract class PayStrategy {

// Payment logic method
abstract void algorithmInterface();

}
  1. Define and implement wechat payment
package com.lijie;

class PayStrategyA extends PayStrategy {

void algorithmInterface() {
System.out.println(" Wechat payment ");
}
}
  1. The realization of Alipay payment is defined
package com.lijie;

class PayStrategyB extends PayStrategy {

void algorithmInterface() {
System.out.println(" Alipay pay ");
}
}
  1. Define and realize UnionPay payment
package com.lijie;

class PayStrategyC extends PayStrategy {

void algorithmInterface() {
System.out.println(" UnionPay payment ");
}
}
  1. Define the following maintenance algorithm strategy
package com.lijie;// Use context to maintain algorithm strategy 

class Context {

PayStrategy strategy;

public Context(PayStrategy strategy) {
this.strategy = strategy;
}

public void algorithmInterface() {
strategy.algorithmInterface();
}

}
  1. Run the test
package com.lijie;

class ClientTestStrategy {
public static void main(String[] args) {
Context context;
// Using payment logic A
context = new Context(new PayStrategyA());
context.algorithmInterface();
// Using payment logic B
context = new Context(new PayStrategyB());
context.algorithmInterface();
// Using payment logic C
context = new Context(new PayStrategyC());
context.algorithmInterface();
}
}

Observer mode

1. What is the observer model

  • Let's start with the behavioral model , Behavioral patterns focus on the interaction between objects in a system , Solve the system in the run-time objects between the mutual communication and cooperation , Further clarify the responsibilities of the object .
  • Observer mode , It's a behavioral model , It's also called release - A subscription model , He defines a one to many dependency between objects , When an object changes state , All objects that depend on it are notified and automatically updated .

2. The responsibility of the model

  • The observer model is mainly used for 1 Yes N The notice of . When the state of an object changes , He needs to tell a series of people in time , Make them respond .

There are two ways to do this :

  1. PUSH : Every time the notification is broadcast to all observers , All observers can only passively receive .
  2. PULL : As long as the observer knows the situation , As for when to get content , What to get , You can make your own decisions .

3. Observer mode application scenario

  1. Associated behavior scenarios , It should be noted that , Association behavior is divisible , instead of “ Combine ” Relationship . Event multi-level trigger scenario .
  2. Cross system message exchange scenario , Such as message queuing 、 The processing mechanism of event bus .

4. The code implements observer mode

  1. Define the abstract observer , Each implementation class that implements the interface is a concrete observer .
package com.lijie;

// Observer interface , It's used to store the observer's shared method
public interface Observer {
// Observer method
void update(int state);
}
  1. Define specific observers
package com.lijie;

// Concrete observer
public class ObserverImpl implements Observer {

// The attributes of the specific observer
private int myState;

public void update(int state) {
myState=state;
System.out.println(" Received a message ,myState Value changed to :"+state);
}

public int getMyState() {
return myState;
}
}
  1. Define the theme . Subject definition observer array , And increase 、 Delete and notify operations .
package com.lijie;

import java.util.Vector;

// Define the theme , And define the observer array , And increase 、 Delete and notify operations .
public class Subjecct {
// The storage set of observers , Not recommended ArrayList, Thread unsafe ,
private Vector<Observer> list = new Vector<>();

// Register observer method
public void registerObserver(Observer obs) {
list.add(obs);
}
// Delete observer method
public void removeObserver(Observer obs) {
list.remove(obs);
}

// Notify all observers to update
public void notifyAllObserver(int state) {
for (Observer observer : list) {
observer.update(state);
}
}
}
  1. Define specific , He inherited Subject class , Realize specific business here , In specific projects , There will be many of them .
package com.lijie;

// Specific themes
public class RealObserver extends Subjecct {
// The properties of the observed object
private int state;
public int getState(){
return state;
}
public void setState(int state){
this.state=state;
// The theme object ( Target audience ) Value changes
this.notifyAllObserver(state);
}
}
  1. Run the test
package com.lijie;

public class Client {

public static void main(String[] args) {
// Target audience
RealObserver subject = new RealObserver();
// Create multiple observers
ObserverImpl obs1 = new ObserverImpl();
ObserverImpl obs2 = new ObserverImpl();
ObserverImpl obs3 = new ObserverImpl();
// Register in the observation queue
subject.registerObserver(obs1);
subject.registerObserver(obs2);
subject.registerObserver(obs3);
// change State state
subject.setState(300);
System.out.println("obs1 Observer MyState The status value is :"+obs1.getMyState());
System.out.println("obs2 Observer MyState The status value is :"+obs2.getMyState());
System.out.println("obs3 Observer MyState The status value is :"+obs3.getMyState());
// change State state
subject.setState(400);
System.out.println("obs1 Observer MyState The status value is :"+obs1.getMyState());
System.out.println("obs2 Observer MyState The status value is :"+obs2.getMyState());
System.out.println("obs3 Observer MyState The status value is :"+obs3.getMyState());
}
}

That's all for the article , you 're right , be without

The observer method public void removeObserver(Observer obs) { list.remove(obs); }

// Notify all observers to update 
public void notifyAllObserver(int state) {
for (Observer observer : list) {
observer.update(state);
}
}
  1. Define specific , He inherited Subject class , Realize specific business here , In specific projects , There will be many of them .

package com.lijie;

// Specific themes
public class RealObserver extends Subjecct {
// The properties of the observed object
private int state;
public int getState(){
return state;
}
public void setState(int state){
this.state=state;
// The theme object ( Target audience ) Value changes
this.notifyAllObserver(state);
}
}

Run the test

package com.lijie;

public class Client {

public static void main(String[] args) {
// Target audience
RealObserver subject = new RealObserver();
// Create multiple observers
ObserverImpl obs1 = new ObserverImpl();
ObserverImpl obs2 = new ObserverImpl();
ObserverImpl obs3 = new ObserverImpl();
// Register in the observation queue
subject.registerObserver(obs1);
subject.registerObserver(obs2);
subject.registerObserver(obs3);
// change State state
subject.setState(300);
System.out.println("obs1 Observer MyState The status value is :"+obs1.getMyState());
System.out.println("obs2 Observer MyState The status value is :"+obs2.getMyState());
System.out.println("obs3 Observer MyState The status value is :"+obs3.getMyState());
// change State state
subject.setState(400);
System.out.println("obs1 Observer MyState The status value is :"+obs1.getMyState());
System.out.println("obs2 Observer MyState The status value is :"+obs2.getMyState());
System.out.println("obs3 Observer MyState The status value is :"+obs3.getMyState());
}
}

If it's not necessary , Just prepare the above nine design patterns , It's a little hard to remember all !

The author of this article : The little hero ,
Link to the original text :https://juejin.cn/post/6844904125721772039
The copyright belongs to the author , Please indicate the author of the reprint 、 original text 、 Translators and other source information
Please bring the original link to reprint ,thank
Similar articles