23 design patterns java example code

23 design patterns


Introduction:

1) Design patterns are the useful experience summed up by programmers in the face of similar software engineering design problems. Patterns are not codes, but general solutions to certain types of problems. Design patterns represent best practices. These solutions are the result of trial and error by numerous software developers over a considerable period of time.
2), the essence of the design pattern improves the maintainability, versatility and scalability of the software, and reduces the complexity of the software.
3), <<Design Patterns>> is a classic book, the authors are Erich Gamma, Richard Helm, Ralph Johnson and John Vissides Design (commonly known as "Group of Four GOF")
4), design patterns are not limited to a certain language, java, php, c++ all have design patterns

  1. why learn

    Design patterns are designed to propose solutions to common (recurring) problems in software design .

    to solve a certain problem

    In the process of writing software, programmers face challenges from coupling, cohesion, maintainability, scalability, reusability, and flexibility. The design pattern is to make the program have better

    1. code reuse
    2. readability
    3. Scalability (it is very convenient when new functions need to be added)
    4. Reliability (adding new functions has no effect on the original functions)
    5. Make the program present the characteristics of high cohesion and low coupling
  2. What is the use

    When a project is developed, if a customer proposes to add new functions, the use of design patterns will have good scalability

    It turns out that it is easier for programmers to leave and take over projects

  3. how to use

    1), Level 1: Not long after I started learning programming, I have heard about design patterns
    2), Level 2: I have a long time of programming experience, and I have written a lot of code, which uses design patterns, but. But I don’t know
    3), the third layer: I have learned the design pattern, found that I am already using it, and found some new patterns that are very useful
    4), the fourth layer: read a lot of source code and Framework, in which you can see other people's design patterns, and be able to appreciate the subtleties and benefits of design patterns.
    5), Level 5: The code was written, and I didn't realize that I used the design pattern, and I wrote it proficiently.

1. The 6/7 principles of the design pattern:

● The core idea of ​​design principles
1) Find out the places that may need to be changed in the application, separate them, and don't mix them with the code that does not need to be changed.
2), programming for the interface, not for the implementation of programming.
3) Strive for loosely coupled design between interactive objects

Memorized:

1. The Open Close Principle
is open to extension (to the provider) and closed to modification (to the user).
2. Liskov Substitution Principle (Liskov Substitution Principle)
Only when the base class can be replaced by the derived class and the function of the software unit is not affected, the base class can be truly reused, and the derived class can also be added on the basis of the base class new behavior.
3. Dependence Inversion Principle (Dependence Inversion Principle)
This is the basis of the opening and closing principle. For interface programming, it depends on abstraction and not on concreteness.
4. Interface Segregation Principle (Interface Segregation Principle)
uses multiple isolated interfaces to reduce coupling. A class's dependency on another class should be based on the smallest interface.
5. Demeter Principle (Demeter Principle)
An entity should interact with other entities as little as possible, so that the functional modules of the system are relatively independent.
6. The principle of composite reuse (Composite Reuse Principle)
is to try to use synthesis/aggregation instead of inheritance. Inheritance actually breaks the encapsulation of the class, and the methods of the superclass may be modified by the subclass.

  1. Single Responsibility Principle

    A class should only be responsible for one responsibility. For example, Class A is responsible for two different responsibilities: Responsibility 1 and Responsibility 2. When the requirements of responsibility 1 change and A is changed, it may cause execution errors of responsibility 2, so the granularity of class A needs to be decomposed into the class A1 and the class A2

    1. Reduce the complexity of the class, a class is responsible for only one responsibility.
    2. Improve the readability and maintainability of the class
    3. Reduce the risk of change
    4. Under normal circumstances, we should abide by the principle of single responsibility . Only when the logic is simple enough can the principle of single responsibility be violated in the code; only when the number of methods in the class is small enough can the principle of single responsibility be maintained at the method level
  2. Interface Segregation Principle

    ​Split interface

    1. A client should not depend on interfaces it does not need

    2. A class's dependency on another class should be based on the smallest interface.

  3. Dependency Inversion Principle

    1. The central idea of ​​Dependency Inversion is interface-oriented programming .
    2. What depends on is that abstractions should not depend on details (concrete), details should depend on abstractions.
    3. Use the interface . The purpose of the abstract class is to practice the specification without involving any specific operations , and leave the task of showing the details to the implementation class to complete
    4. Notes and details of the Dependency Inversion Principle.
      1. Low-level modules should have abstract classes or interfaces as much as possible, or both have better program stability.
      2. The declaration type of the variable should be an abstract class or interface as much as possible, so that there is a buffer layer between our variable reference and the actual object, which is easy for program expansion and optimization.
      3. Follow the Liskov substitution principle when inheriting.
  4. Liskov Substitution Principle

    1. All references to the base class must be able to transparently use the in-duration object.
    2. When using inheritance, follow the Liskov substitution principle, and try not to override the methods of the parent class in the subclass.
    3. The Liskov substitution principle tells us that inheritance actually enhances the coupling of two classes, **under appropriate circumstances, it can be aggregated, combined (injected), and dependent (interface replaced). to solve the problem. ** Let the two classes inherit from a more basic class.
  5. open close principle ocp

    1. The Open Closed Principle is the most basic and important design principle in programming.
    2. A software entity such as classes, modules and functions should be open for extension (for the provider) and closed for modification (for the consumer) . Build frameworks with abstractions and extend details with implementations.
    3. When the software needs to change, try to implement the change by extending the behavior of the software entity instead of modifying the existing code.
    4. Other principles are followed in programming, and the purpose of using design patterns is to follow the principle of opening and closing.
  6. Law of Demeter

    1. An object should keep minimal knowledge about other objects.
    2. Classes are more closely related to classes. The greater the degree of coupling.
    3. Demeter Principle (Demeter Principle) is also called the least known law , and it is the one that a class depends on itself. The less you know , the better , that is to say, for dependent humans, no matter how complicated it is, try to encapsulate the logic inside the class. Do not disclose any information except for providing public methods.
    4. Demeter's Law. There is also a simpler definition, communicating only with immediate friends. Appears in member variables method parameters, method return values ​​that are called direct friends. Whereas local variables appear, that's my immediate friend. Unfamiliar classes are best not to appear inside the class in the form of local variables.
    5. Dimit's Law Notes and Details
      1. The core of Dimit's law is to reduce the coupling between classes.
      2. But note that unnecessary dependencies are reduced due to each class. Because Dimit's law only requires reduction, the coupling relationship between objects between classes does not require no dependencies at all.
  7. Synthetic Reuse Principles

    The principle is to try to use composition/aggregation instead of inheritance.

1), UML class diagram definition

  1. UML–Unified modeling language UML (Unified Modeling Language), is a language tool for software system analysis and design, which is used to help software developers think and record the results of ideas

  2. UML itself is a set of symbols, just like mathematical symbols and chemical symbols, these symbols are used to describe the various elements in the software model and the relationship between them, such as classes, interfaces, implementations, generalizations, dependencies, combinations , aggregation, etc.

  3. Use UML to model, the commonly used tools are RationalRose, and some plug-ins can also be used to model.

    Common Commonly used
    Note For your UML annotation
    Class represents a class, you can add attributes and methods.
    Interface represents an interface.
    Relation
    Dependency depends on.
    Association Association.
    Generalization means generalization (inheritance.)
    Realization means realization.
    Aggregation aggregation.
    Composite combination. Coupling is stronger than aggregation.

    1), use case diagram (use case)
    2), static structure diagram: class diagram , object diagram, package diagram, component diagram, deployment diagram.
    3), dynamic behavior diagram: interaction diagram (sequence diagram and collaboration diagram), state diagram , Activity Diagram

    Class diagram: It describes the relationship between classes and classes, and is the core of UML diagrams

2) Detailed explanation of UML class diagram

1) It is used to describe the composition of classes (objects) in the system and various static relationships between classes (objects).
2), the relationship between classes: dependency, generalization (inheritance), implementation, association, aggregation and combination.

1. Detailed description of the name

Dependency

We call it a dependency if there are

  1. , The other party is used in the class
    2), if it is a member attribute of the class
    3), if it is the return type of the method
    4), it is the parameter type received by the method
    5), used in the method

As long as each other is used in the class, there is a dependency relationship between them. Without the other party, even the compilation would not pass.

public class PersonServiceBean {
    
    
	private PersonDao personDao;/public void save(Person person){
    
    }
	public IDCard getIDCard(Integer personid){
    
    }
	public void modifyO{
    
    
		Depatment department= new Depatment{
    
    };
	}
}
public class PersonDao{
    
    }
public class IDCard{
    
    }
public class Person{
    
    }
public class Department{
    
    }

Generalization

The generalization relationship is actually an inheritance relationship, which is a special case of the dependency relationship

1), the generalization relationship is actually an inheritance relationship
2), if class A inherits class B, we say that there is a generalization relationship between A and B

public abstract class DaoSupport{
    
    
	public void save(Object entity){
    
    }
	public void delete(Object id){
    
     }
}
public class PersonServiceBean extends Daosupport{
    
    }

Realization

The implementation relationship is actually that class A implements class B , which is a special case of dependency relationship

public interface PersonService {
    
    
	public void delete(Interger id){
    
    }
}
public class PersonServiceBean implements PersonService {
    
    
	public void delete(Interger id){
    
    }
}

Association

Association relationship is actually the connection between classes. It is a special case of dependency relationship
. Association is navigable: that is, bidirectional relationship or unidirectional relationship

I use you for one-way one-to-one relationships.

public class Person {
    
    
	private IDCard card;
}
public class IDCard{
    
    }

Two-way - one-to-one relationship I use you and you use me.

public class Person {
    
    
	private IDCard card;
}
public class IDCard{
    
    
	private Person person{
    
     }
}

Aggregation

  1. The aggregation relationship (Aggregation) represents the relationship between the whole and the part, and the whole and the part can be separated . Aggregation
    relationship is a special case of association relationship, so it has associated navigation and multiplicity.
  2. For example: A computer is composed of a keyboard, a monitor, a mouse, etc.; each
    accessory that makes up a computer can be separated from the computer, and is represented by a solid line with a hollow rhombus:
public class Computer {
    
    
	private Mouse mouse; 		//鼠标可以和computer分离
	private Moniter moniter;	//显 示器可以和Computer分离
	public void setMouse(Mouse mouse) {
    
    
		this.mouse = mouse ;
	}
	public void setMoniter(Moniter moniter) {
    
    
		this.moniter = moniter;
	}
}

The absence of these two classes (Mouse and Moniter) has no effect on the creation of the Computer class.

Composite

  1. Combination relationship: It is also the relationship between the whole and the part, but the whole and the part cannot be separated . The solid diamond points to the class used

As long as the Person creates the Head, it is created, so it cannot be separated. A person can have no ID card, but not a head.

public class Person{
    
    
	private IDCard card;
	private Head head = new Head();
	public class IDCard{
    
    }
	public class Head{
    
    }
}
  1. However, if in the program, the Person entity defines the cascading deletion of IDCard, that is, when deleting Person, it is deleted together with IDCard, then IDCard and Person are combined.

Two, the design pattern is divided into three types 23 kinds

For novices who are short on time, first follow these few, you can go to the recruitment website to have a look, the required design pattern

  1. Creational patterns: singleton pattern, builder pattern, factory pattern,
  2. Structural patterns: adapter pattern, proxy pattern
  3. Behavioral patterns: template method pattern, strategy pattern

Design patterns are divided into three types, a total of 23 types

  1. Creational patterns: singleton pattern, abstract factory pattern, prototype pattern, builder pattern, worker pattern.

  2. Structural patterns: Adapter pattern, Bridge pattern, Decoration pattern, Composite pattern, Appearance pattern, Flyweight pattern, Proxy pattern.

  3. Behavioral patterns: template method pattern, command pattern, visitor pattern, iterator pattern, observer pattern, intermediary pattern, memo pattern, interpreter pattern (Interpreter pattern), state pattern, strategy pattern, responsibility chain pattern (responsibility chain model).

    Note: Different books have slightly different categories and names

1), creation mode

1 Creational patterns: singleton pattern, abstract factory pattern, prototype pattern, builder pattern, factory pattern .

After learning a category, take time to think about what this category has and what each mode does

1. Singleton mode,

The so-called singleton design pattern of a class is to adopt a certain method to ensure that in the entire software system, there can only be one object instance for a certain class , and the class only provides a method (static) to obtain its object instance.

  1. Hungry style (static constant)
    2) Hungry style (static code block)
    3) Lazy style (thread unsafe) – not recommended
    4) Lazy style (thread safe, synchronous method) – not recommended
    5) Lazy style (thread safe , synchronized code block)
    6) double check
    7) static inner class
    8) enumeration
  • Precautions and details of the singleton mode
    1). The singleton mode ensures that only one object of this class exists in the system memory, saving system resources. For some objects that need to be created and destroyed frequently, using the singleton mode can improve system performance
    2) When you want to instantiate a singleton class, you must remember to use the corresponding object acquisition method instead of using new 3) Scenarios for
    singleton mode: objects that need to be created and destroyed frequently, It takes too much time or resources to create objects (ie: heavyweight objects), but frequently used objects, tool objects, objects that frequently access databases or files (such as data sources, session factories~, etc.)

1. Hungry Chinese style (static constant)

Explanation of advantages
and disadvantages: 1) Advantages: This method of writing is relatively simple, that is, the instantiation is completed when the class is loaded. Thread synchronization issues are avoided.
2) Disadvantage: The instantiation is completed when the class is loaded, which does not achieve the effect of Lazy Loading. If this instance is never used from the beginning to the end, it will cause a waste of memory

Conclusion: This singleton mode is available and may cause memory waste

public class Mgr01 {
    
    
	private static final Mgr01 INSTANCE = new Mgr01();
	private Mgr01(){
    
    }
	public static Mgr01 getInstance(){
    
     return INSTANCE; }
	public void m(){
    
     System.out.println("m"); }
	public static void main(String[] args) {
    
    
		Mgr01 mg1 = Mgr01.getInstance();
		Mgr01 mg2 = Mgr01.getInstance();
		System.out.println(mg1.hashCode()+"\n"+mg2.hashCode());
	}
}

2. Lazy man style, double check

1), the Double-Check concept is often used in multi-threaded development, as shown in the code, we have performed two if (singleton == nul) checks, so that thread safety can be guaranteed.
2) In this way, the instantiation code only needs to be executed once, and when it is accessed again later, judge if (singleton == nlll), directly return the instantiation object, and avoid repeated method synchronization. 3), thread safety; delayed loading
; Higher efficiency
4), conclusion: In actual development, it is recommended to use this singleton design pattern

public class Mgr03 {

public class Mgr03 {
    
    
	private static Mgr03 INSTANCE;
	private Mgr03(){
    
    }
	public static Mgr03 getInstance(){
    
    
		if(INSTANCE == null){
    
    
			synchronized (Mgr03.class) {
    
    
				if(INSTANCE == null){
    
    
					INSTANCE = new Mgr03();
					return INSTANCE;
				}
			}
		}
		return INSTANCE; 
	}
}

3. Static inner class

1) This method uses a class loading mechanism to ensure that there is only one thread when initializing an instance.
2) The static internal class method does not instantiate the Singleton class immediately when it is loaded, but calls the getInstance method when it needs to be instantiated, and then the SingletonInstance class is loaded to complete the instantiation of the Singleton.
3) The static properties of the class will only be initialized when the class is loaded for the first time, so here, the JVM helps us ensure the safety of the thread. When the class is initialized, other threads cannot enter.
4), Advantages: avoid thread insecurity, use the characteristics of static internal classes to achieve lazy loading, high efficiency
5), conclusion: recommended to use .

  1. The role of the volatile keyword: to ensure the visibility of variables (visibility). For variables modified by the volatile keyword, if the value changes, other threads can see it immediately to avoid dirty reads. As shown in the following code snippet, after isShutDown is set to true, the doWork method is still executed. If the isShutDown variable is modified with volatile, this problem can be avoided.
public class Mgr04 {
    
    

	private static volatile Mgr04 INSTANCE;
	
	private Mgr04(){
    
    }
	
	private static class MgrSon{
    
    
		private static final Mgr04 INSTANCES = new Mgr04();
	}
	public  static Mgr04 getInstance(){
    
    
		try{
    
    
			Thread.sleep(1);
			}catch(Exception e){
    
    
				e.printStackTrace();
			}
		return MgrSon.INSTANCES;
	}
	
	public static void main(String[] args) {
    
    
		for(int i=0;i<1000;i++){
    
    			
			new Thread(new Runnable(){
    
    
				@Override
				public void run() {
    
    
					System.out.println(getInstance().hashCode());
				}
			}).start();
		}
	}
}

4. Enumeration

1) This implements the singleton pattern with the help of the enumeration added in JDK1.5. Not only can it avoid multi-thread synchronization problems, but it can also prevent deserialization from recreating new objects.
2), this method is advocated by Josh Bloch, the author of Effective Java
3), conclusion: recommended

 //语法上是最好的,但是是一个枚举,java的创始人之一写的书上的Effective推荐的写法
public enum Mgr {
    
    
	INSTANCE;
	public static void main(String[] args) {
    
    
		for(int i=0;i<1000;i++){
    
    
         //有laman简写   效果是一样的     用于实现只有一个方法的接口    ()->{}
			new Thread(new Runnable(){
    
    
				@Override
				public void run() {
    
    
					System.out.println(INSTANCE.hashCode());
				}
			}).start();
		}
	}
}

2. Factory pattern,

1) The significance of the factory pattern
Extract the code of the instantiated object and put it into a class for unified management and maintenance, so as to achieve the
decoupling of the dependency relationship with the main project. Thereby improving the expansion and maintainability of the project.
2), three factory modes (simple factory mode, factory method mode, abstract factory "mode)
3), the principle of dependent abstraction in design mode
➢ When creating an object instance, do not directly create a new class, but put the action of this new class in In the method of each factory: and return. Some books say that variables should not directly hold references to concrete classes.
➢Do not let classes inherit concrete classes, but inherit abstract classes or implement interface (interface)
➢ Do not override methods already implemented in the base class.

1. Simple factory pattern

Basic introduction:
1). The simple factory pattern belongs to the creation pattern and is a kind of factory pattern. The simple factory pattern is to determine which instance of a product class to create by a factory object. The simple factory pattern is the simplest and most practical pattern in the factory pattern family
2), simple factory pattern: defines a class that creates objects, and this class encapsulates the behavior (code) of instantiating objects
3), in software development, when When we will use a large number of objects to create a certain type, a certain type, or a certain batch of objects, we will use the factory pattern

The advantage is that it is easy to understand and easy to operate.
The disadvantage is that it violates the OCP principle of the design pattern, that is, it is open to extension and closed to modification. That is, when we add new functions to the class, try not to modify the code, or modify the code as little as possible.

//披萨类
public abstract class Pizza {
    
    
	String name;
	public void prepare(){
    
     }
	public void setName(String name){
    
    
		this.name=name;
	}
	public void bake(){
    
    
		System.out.println(name+"------正在烤");
	}
	public void cut(){
    
    
		System.out.println(name+"------正在切!");
	}
	public void box(){
    
    
		System.out.println(name+"------打包!");
	}
}
public class PepperPizza extends Pizza{
    
    
//披萨种类
	public void prepare(){
    
    
		setName("胡椒披萨");
		System.out.println("PepperPizza");
	}
}
//制作披萨的工厂,只负责制造披萨
public class PizzaFactory {
    
    
	public Pizza createPizza(String orderType){
    
    
		Pizza piza = null;
		if(orderType.equals("Greek")){
    
    
			piza = new GreekPizza();
		}else if(orderType.equals("Cheese")){
    
    
			piza = new CheesePizza();
		}else if(orderType.equals("Pepper")){
    
    
			piza = new PepperPizza();
		}
		return piza;
	}
}
//使用工厂制造披萨的类,创建披萨的方式有很多种,这个算是烤的,可能还有冷的、麻辣、香辣、甜...
public class OrdType {
    
    
	PizzaFactory pizzaFactory;
	Pizza pizza;
	OrdType(PizzaFactory pizzafact){
    
    
		this.pizzaFactory = pizzafact;
		setPizzaFactory();
	}
	public void setPizzaFactory(){
    
    
		String order = "";
		do{
    
    
			order = getType();
			pizza = pizzaFactory.createPizza(order);
			if(pizza != null){
    
    
				System.out.println("欢迎制作披萨!");
				pizza.prepare();
				pizza.bake();
				pizza.cut();
				pizza.box();
				System.out.println("制作完成!");
			}else{
    
    
				System.out.println("订购披萨失败,没有您需要的披萨");
				break;
			}
		}while(true);
	}
	public String getType(){
    
    
		try{
    
    
			BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("input pizza type:");
			String str = strin.readLine();
			return str;
		}catch(Exception e){
    
    
			e.printStackTrace();
		}
		return "";
	}
}
//真正使用的类,可能是控制器,服务层
public class MakePizza {
    
    
	public static void main(String[] args) {
    
    
		new OrdType(new PizzaFactory());
		System.out.println("Make pizza over!");
	}
}

2. Factory method pattern

Introduction to factory method pattern:

		1. 工厂方法模式设计方案:将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现。

  			2. 工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
public abstract class Pizza {
    
    
	String name;
	public abstract void prepare();
	
	public void setName(String name){
    
    
		this.name=name;
	}
	
	public void bake(){
    
    
		System.out.println(name+"------正在烤");
	}
	
	public void cut(){
    
    
		System.out.println(name+"------正在切!");
	}
	
	public void box(){
    
    
		System.out.println(name+"------打包!");
	}
}
public class BJCheesePizza extends Pizza{
    
    
	public void prepare(){
    
    
		setName("北京奶酪披萨");
		System.out.println(name);
	}
}
public class BJGreekPizza extends Pizza{
    
    
	public void prepare(){
    
    
		setName("北京希腊披萨");
		System.out.println(name);
	}
}
//使用工厂制造披萨的类,创建披萨的方式有很多种,这个算是烤的,可能还有冷的、麻辣、香辣、甜...
public abstract class OrdType {
    
    
   public abstract Pizza setPizzaFactory(String order);
	//公共的方法由抽象的构造器写出来
	OrdType(){
    
    
		Pizza pizza = null;
		String order = null;
		do{
    
    
			order = getType();
			pizza = setPizzaFactory(order);//具体方法由子类实现
			if(pizza == null){
    
    
				break;
			}
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
			System.out.println("您的"+pizza.name+"请收好!");
		}while(true);
	}
	public String getType() {
    
    
		try{
    
    
			BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("input pizza type:");
			String str = strin.readLine();
			return str;
		}catch(Exception e){
    
    
			e.printStackTrace();
		}
		return "";
	}
}
public class BJOrdType extends OrdType{
    
    
	@Override
	public Pizza setPizzaFactory(String order) {
    
    
		Pizza pizza = null;
		if(order.equals("Cheese")){
    
    
			pizza = new BJCheesePizza();
		}else if(order.equals("Greek")){
    
    
			pizza = new BJGreekPizza();
		}else{
    
    
			System.out.println("没有你要的种类");
		}
		return pizza;
	}	
}
//制作披萨的抽象工厂类,
public abstract class PizzaFactory {
    
    
	public abstract Pizza createPizza(String orderType);
}
public class BJPizzaFactory extends PizzaFactory{
    
    
	@Override
	public Pizza createPizza(String orderType) {
    
    
		Pizza pizza = null;
		if(orderType.equals("Cheese")){
    
    
			pizza = new BJCheesePizza();
		}else{
    
    
			System.out.println("您要的披萨不存在!");
		}
		return pizza;
	}
}
public class TestBjPizza {
    
    
	public static void main(String[] args) {
    
    
		new BJOrdType();
		System.out.println("结束!");
	}
}

3. Abstract factory pattern

1), abstract factory mode: defines an interface for creating related or dependent object clusters without specifying specific classes
2), abstract factory mode can integrate simple factory mode and factory method mode.
3) From a design perspective, the abstract factory pattern is an improvement on the simple factory pattern (or called progressive abstraction).
4) Abstract the factory into two layers, AbsFactory (abstract factory) and concrete factory subclasses. Programmers can use the corresponding factory subclass according to the type of object to be created. This turns a single simple factory class into a factory cluster, which is more conducive to code maintenance and expansion.
5), class diagram

public abstract class Pizza {
    
    
	String name;
	public abstract void prepare();
	public void setName(String name){
    
    
		this.name=name;
	}
	public void bake(){
    
    
		System.out.println(name+"------正在烤");
	}
	public void cut(){
    
    
		System.out.println(name+"------正在切!");
	}
	public void box(){
    
    
		System.out.println(name+"------打包!");
	}
}
public class BJCheesePizza extends Pizza{
    
    
	public void prepare(){
    
    
		setName("北京奶酪披萨");
		System.out.println(name);
	}
}
public class BJGreekPizza extends Pizza{
    
    
	public void prepare(){
    
    
		setName("北京希腊披萨");
		System.out.println(name);
	}
}
//接口
public interface IPizzaFactory {
    
    
	Pizza createPizza(String orderType);
}
public class BJFactory implements IPizzaFactory{
    
    
	@Override
	public Pizza createPizza(String orderType) {
    
    
		Pizza pizza = null;
		if(orderType.equals("Cheese")){
    
    
			pizza = new BJCheesePizza();
		}else if(orderType.equals("Greek")){
    
    
			pizza = new BJGreekPizza();
		}else{
    
    
			System.out.println("您要的披萨不存在!");
		}
		return pizza;
	}
}
public class BJOrdType {
    
    //北京工厂子类,伦敦的同理
	 IPizzaFactory iPizzaFactory;
   OrdType(IPizzaFactory Factory){
    
    
		setiPizzaFactory(Factory);
	}
	//只要是成员变量都是要有set方法的,不然就没有意义
	private void setiPizzaFactory(IPizzaFactory factory) {
    
    
		this.iPizzaFactory = factory;
		Pizza pizza= null;
		String order = null;
		do{
    
    
			order = getType();//这里的工厂可能是北京的,也有可能是伦敦的
			pizza = iPizzaFactory.createPizza(order); 
			if(pizza == null){
    
    
				break;
			}
         System.out.println("使用抽象工厂模式");
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
			System.out.println("您的"+pizza.name+"请收好!");
		}while(true);
	}
	public String getType() {
    
    
		try{
    
    
			BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("input pizza type:");
			String str = strin.readLine();
			return str;
		}catch(Exception e){
    
    
			e.printStackTrace();
		}
		return "";
	}
}
public class TestFactory {
    
    
//测试类
	public static void main(String[] args) {
    
    
		new OrdType(new BJFactory());
		System.out.println("结束~!");
	}
}
运行结果
input pizza type:
Greek
使用抽象工厂模式
北京希腊披萨
北京希腊披萨------正在烤
北京希腊披萨------正在切!
北京希腊披萨------打包!
您的北京希腊披萨请收好!
input pizza type:
asdf
您要的披萨不存在!
结束~

4. Prototype pattern,

1), Prototype mode (Prototype mode) refers to: use prototype instances to specify the type of object to be created, and create new objects by copying these prototypes 2), Prototype mode is
a creational design mode that allows - an object to be created again In addition - a customizable object does not need to know the details of how to create
3), the working principle is: by passing a prototype object to the object to be created, the objects to be created are implemented by requesting the prototype object to copy themselves Creation, that is, the object.clone()
4), the understanding of the image: Sun Dasheng pulls out the monkey hair and transforms into other Sun Dasheng

The prototype mode realizes the cloning of classes. If there is an additional attribute in the latter class, the cloned attribute will still exist.

① Shallow copy is a reference to the object.

  1. For member variables whose data type is a basic data type, shallow copy will directly perform value transfer, that is,
    copy the attribute value - - to a new object.
  2. For member variables whose data type is a reference data type, for example, a member variable is an array,
    an object of a certain class , etc., then shallow copy will perform reference transfer , that is, only the reference value (
    memory Make a copy for the new object. Because in fact the member variables of the two objects point to the same
    instance. In this case, modifying the member variable in one object will affect
    the value of the member variable in another object
  3. Shallow copy is implemented using the default clone() method
    sheep = (Sheep) super.clone();
//                需要实现Cloneable接口
public class Sheep implements Cloneable{
    
    
	private int age;
	private String name;
	private String color;
	public Sheep friend;
    @Override		//从写Object的clone类
	protected Object clone(){
    
      //如果属性只有基本数据类型,那么默认超类方法即可
      Sheep sheep = null;
		try{
    
    
			sheep = (Sheep)super.clone();
		}catch(Exception e){
    
    
			System.out.println(e.getMessage());
		}
		return sheep;
   }
}
   public static void main(String[] args) {
    
    
		Sheep sheep = new Sheep("tom",1,"white");
		sheep.friend = new Sheep("jack",2,"black");
		
		Sheep sheep1 = (Sheep)sheep.clone();
		Sheep sheep2 = (Sheep)sheep.clone();
		Sheep sheep3 = (Sheep)sheep.clone();

		System.out.println(sheep+"------  sheep.friend="+sheep.friend.hashCode());
		System.out.println(sheep1+"------  sheep.friend="+sheep1.friend.hashCode());
		System.out.println(sheep2+"------  sheep.friend="+sheep2.friend.hashCode());
		System.out.println(sheep3+"------  sheep.friend="+sheep3.friend.hashCode());
	}
Sheep [age=1, name=tom, color=white]------  sheep.friend=5433634
Sheep [age=1, name=tom, color=white]------  sheep.friend=5433634
Sheep [age=1, name=tom, color=white]------  sheep.friend=5433634
Sheep [age=1, name=tom, color=white]------  sheep.friend=5433634

② Basic introduction to deep copy

  1. Copy the member variable values ​​of all primitive data types of the object
  2. Apply for storage space for all member variables of reference data type, and copy
    the object referenced by each member variable of reference data type until all objects reachable by the object. That is to say, the deep copy of the object needs to
    copy the entire object
  3. Deep copy implementation method 1: Rewrite the clone method to implement deep copy,
  4. Deep copy implementation method 2: Realize deep copy through object serialization
method one:
public class Sheep implements Cloneable,Serializable{
    
    
	private int age;
	private String name;
	private String color;
	public Sheep1 friend;
   	@Override
	protected Object clone(){
    
    
		Sheep sheep = null;
		try{
    
    
			sheep = (Sheep)super.clone();
			sheep.friend = (Sheep1)friend.clone();
		}catch(Exception e){
    
    
			System.out.println(e.getMessage());
		}
		return sheep;
	}
   //friend 引用指向重写父类clone方法
public class Sheep1 implements Serializable,Cloneable{
    
    
	String sheep1 = "sheep1";
	@Override
	public String toString() {
    
    
		return "Sheep1 [sheep1=" + sheep1 + "]";
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
    
    
		return super.clone();
	}
}
Method two,
  • The stream is used to serialize and deserialize, convert to bytes, and convert to objects, even if the bytes are the same, but the hashCode() of the converted objects will be different.
public class Sheep1 implements Serializable{
    
    
	String sheep1 = "sheep1";

	@Override
	public String toString() {
    
    
		return "Sheep1 [sheep1=" + sheep1 + "]";
	}
}
//只要实现Serializable接口就行了。
   public class Sheep implements Serializable{
    
    
	private int age;
	private String name;
	private String color;
	public Sheep1 friend;
      //方式二、运用流存到内存的序列化原理,进行读写操作来克隆
	Sheep copy(){
    
    
		ObjectInputStream ois = null;
		ByteArrayInputStream bais = null;
		ObjectOutputStream oos = null;
		ByteArrayOutputStream baos = null;
		try{
    
    //可以这样理解,对象转换到字节叫序列化,写出去叫out
			baos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(baos);
			//write is a Object,this is 当前 Object 
			oos.writeObject(this);
			//相当于转成了字节,然后把字节转成Object回来,叫反序列化,
			//baos.toByteArray()意思是拷贝一份刚刚序列化的
			bais = new ByteArrayInputStream(baos.toByteArray());
			ois = new ObjectInputStream(bais);
			//读的是Object method name is readObject()
			Sheep sheep = (Sheep)ois.readObject();
			return sheep;
		}catch(Exception e){
    
    
			System.out.println(e.getMessage());
		}
      try{
    
    //记得要关闭流
			ois.close();
			bais.close();
			oos.close();
			baos.close();
		}catch(Exception e){
    
    
			e.printStackTrace();
		}
		return null;
	}
}
Sheep [age=1,name=tom,color=white,friend=Sheep1 [sheep1=sheep1]]sheep.friend=21598637
Sheep [age=1,name=tom,color=white,friend=Sheep1 [sheep1=sheep1]]sheep.friend=26887603
Sheep [age=1,name=tom,color=white,friend=Sheep1 [sheep1=sheep1]]sheep.friend=10069385
Sheep [age=1,name=tom,color=white,friend=Sheep1 [sheep1=sheep1]]sheep.friend=3615232
Sheep [age=1,name=tom,color=white,friend=Sheep1 [sheep1=sheep1]]sheep.friend=14519747
Sheep [age=1,name=tom,color=white,friend=Sheep1 [sheep1=sheep1]]sheep.friend=17033014

Pros and cons of the Prototype pattern:

1) When creating a new object is more complicated, you can use the prototype mode to simplify the object creation process and improve efficiency. 2) Instead of reinitializing the
object, you can dynamically obtain the running state of the object.
3) If the original object Changes (increase or decrease attributes), other cloned objects will also have corresponding numbers, no need to modify the code
4), it may require more complicated codes when implementing deep cloning
5), disadvantages: need for each Equipped with a clone method, which is not very difficult for a new class, but when modifying an existing class, its source code needs to be modified, which violates the ocp principle, please pay attention to this point.

5. Builder mode,

  • Notes and Details of the Builder Pattern

1), the client (using the program) does not need to know the details of the internal composition of the product , and the product itself is decoupled from the product creation process , so that the same creation process can create different product objects
2), each specific builder is relatively independent , and has nothing to do with other specific builders, so it is very convenient to replace specific builders or add new specific builders, and users can get different product objects by using different specific builders 3), and can control products more
finely of the creation process. Decompose the creation steps of complex products into different methods, making the creation process clearer and more convenient to use programs to control the creation process
4), adding new specific builders does not need to modify the code of the original class library, the commander class is for Abstract builder class programming, easy system expansion, in line with the "open and close principle"

5) The products created by the builder mode generally have more in common, and their components are similar. If the products are very different, it is not suitable to use the builder mode, so its scope of use is subject to certain restrictions .
6) If the internal changes of the product are complex, it may lead to the need to define many specific builder classes to achieve this change, resulting in a very large system, so in this case, it is necessary to consider whether to choose the builder mode. 7
) , Abstract Factory Mode VS Builder Mode The abstract factory mode realizes the creation of product families. A product family is such a series of products: product combinations with different classification dimensions. The abstract factory mode does not need to care about the construction process, only care about the product It can be produced by any factory. The builder mode requires building products according to a specified blueprint , and its main purpose is to produce a new product by assembling spare parts

The four roles of the builder pattern:
1), Product ( product role): - A specific product object.
2), Builder ( abstract builder ): Create an interface/abstract class specified by each component of a Product object.
3), ConcreteBuilder ( concrete builder ): realize the interface, build and assemble various components.
4) Director ( commander ): build an object using the Builder interface. It is mainly used to create - - a complex object. It has two main functions, one is to isolate the production process of the customer and the object, and the other is to be responsible for controlling the production process of the product object.

public class House {
    
    
	private String baise;
	private String wall;
	private String roofed;
   //补上set、get、toString方法
}
public abstract class HouseBuilder {
    
    
//建造房子的抽象类
	protected House house = new House();
	public House getHouse() {
    
    
		return house;
	}
	public abstract void builderBaise();
	public abstract void builderwall();
	public abstract void roofed();
}
public class CommonHouse extends HouseBuilder{
    
    
//普通房子
	@Override
	public void builderBaise() {
    
    
		house.setBaise("地基5m!");
		System.out.println("打普通地基5m深!");
	}
	@Override
	public void builderwall() {
    
    
		house.setWall("砌墙10cm!");
		System.out.println("砌普通墙10cm厚!");
	}
	@Override
	public void roofed() {
    
    
		house.setRoofed("屋顶3m!");
		System.out.println("盖普通屋顶3m高!");
	}
}
public class HigthBuilder extends HouseBuilder {
    
    
//高楼
	@Override
	public void builderBaise() {
    
    
		house.setBaise("地基25m!");
		System.out.println("打高楼地基25m深!");
	}
	@Override
	public void builderwall() {
    
    
		house.setWall("砌墙20m!");
		System.out.println("砌高楼墙20cm厚!");
	}
	@Override
	public void roofed() {
    
    
		house.setRoofed("屋顶9m!");
		System.out.println("盖高楼屋顶9m高!");
	}
}
public class DirectorHouse {
    
    
//指挥者
	HouseBuilder houseBuilder = null;
	DirectorHouse(HouseBuilder houseBuild){
    
    
		this.houseBuilder = houseBuild;
	}
	public void setHouseBuilder(HouseBuilder houseBuild) {
    
    
		this.houseBuilder = houseBuild;
	}
	//建造顺序由指挥者来决定
	House BuilderHouse(){
    
    
		houseBuilder.builderBaise();
		houseBuilder.builderwall();
		houseBuilder.roofed();
		return houseBuilder.getHouse();
	}
}
public class Client {
    
    
//盖房子的客户      需求方
	public static void main(String[] args) {
    
    
		//盖普通房子
		DirectorHouse dh = new DirectorHouse(new CommonHouse());
		dh.setHouseBuilder(new CommonHouse());
		House house = dh.BuilderHouse();
		System.out.println(house+"\n-----------------------------");
		//盖高楼
		dh.setHouseBuilder(new HigthBuilder());
		System.out.println(dh.BuilderHouse());
	}
}

2), structural model

2 Structural patterns: Adapter pattern, Bridge pattern, Decoration pattern, Composite pattern, Appearance pattern, Flyweight pattern, Proxy pattern .

1. Adapter pattern

  • Basic introduction
    1), Adapter Pattern (Adapter Pattern) converts the interface of a certain class into another interface representation expected by the client. The main purpose is compatibility , so that two classes that cannot work together due to interface mismatch can cooperate Work. Its alias is wrapper (Wrapper)
    2), adapter mode belongs to structural mode
    3), mainly divided into three categories: class adapter mode, object adapter mode, interface adapter mode

  • Working principle
    1), Adapter mode: convert the interface of a class into another interface. Make the class with the original interface incompatible
    2), from the user's point of view, the adapter cannot be seen, it is decoupled
    3) , The user calls the target interface method transformed by the adapter, and the adapter calls the relevant interface method of the adapter

  • Notes and details of the adapter mode
    1), the three naming methods are named according to the form in which the src is given to the Adapter (the form in the Adapter).
    2), class adapter: given as a class, in the Adapter, src is regarded as a class, and inherits the object , in the Adapter, srC is used as an interface to realize
    3), the biggest role of the Adapter mode is to integrate the originally incompatible interfaces - - work together.
    4) In the actual development, the implementation is not limited to the three classic forms we explained

① class adapter mode,

  • Notes and details of the class adapter mode
    1) Java is a single inheritance mechanism, so the class adapter needs to inherit the src class. This is a shortcoming, because it requires that dst must be an interface, which has certain limitations
    ; Methods will be exposed in the Adapter, which also increases the cost of use.
    3) Since it inherits the src class, it can rewrite the methods of the src class according to the requirements, which enhances the flexibility of the Adapter.
public class Voltage220v {
    
    
//电源电压
	public int Voltage220(){
    
    
		int src = 220;
		System.out.println("获得电压"+src+"伏");
		return src;
	}
}
public interface Voltage {
    
    
//电源转换接口
	int charging5v();
	int charging20v();
}
public class VoltageAdatper extends Voltage220v implements Voltage{
    
    
//电源转接口
	public int charging5v() {
    
    
		int src = Voltage220();
		return src/44;
	}
	public int charging20v() {
    
    
		return 0;
	}
}
public class Phone {
    
    
//手机
	void charging(Voltage voltage5v){
    
    
		int src = voltage5v.charging5v();
		if(src == 5){
    
    
			System.out.println("转成5 伏,充电成功!!");
		}else{
    
    
			System.out.println("转化失败!");
		}
	}
}
public class Client {
    
    
//客户
	public static void main(String[] args) {
    
    
		Phone ph = new Phone();
		ph.charging(new VoltageAdatper());
		System.out.println("Charging over!");
	}
}

② object adapter mode,

  • Precautions and details of object adapter mode
    1), object adapter and class adapter are actually the same idea, but they are implemented in different ways. According to the principle of composition reuse, composition is used instead of inheritance, so it solves the limitation that class adapters must inherit src, and no longer requires that dst must be an interface.
    2) The use cost is lower and more flexible.
public class Voltage220v {
    
    
//电源电压
	public int Voltage220(){
    
    
		int src = 220;
		System.out.println("获得电压"+src+"伏");
		return src;
	}
}
public interface Voltage {
    
    
//电源转换接口
	int charging5v();
	int charging20v();
}
public class VoltageAdatper implements Voltage{
    
    
//电源转接口      使用的是聚合关系
	protected Voltage220v voltage220v;
	
	VoltageAdatper(Voltage220v voltage220){
    
    
		this.voltage220v = voltage220;
	}
	public int charging5v() {
    
    
		if(voltage220v == null){
    
    
			System.out.println("exit!");
         return;
		}
		int src = voltage220v.Voltage220();
		return src/44;
	}
	public int charging20v() {
    
    
		return 0;
	}
}
public class Phone {
    
    
//手机
	void charging(Voltage voltage5v){
    
    
		int src = voltage5v.charging5v();
		if(src == 5){
    
    
			System.out.println("转成5 伏,充电成功!!");
		}else{
    
    
			System.out.println("转化失败!");
		}
	}
}
public class Client {
    
    
//客户
	public static void main(String[] args){
    
    
		System.out.println("对象适配器");
		Phone ph = new Phone();
		VoltageAdatper v = new VoltageAdatper(new Voltage220v());
		ph.charging(v); 
		System.out.println("Charging over!");
	}
}

③ Interface adapter mode,

  • Interface Adapter Pattern Introduction
    1), some books are called: Adapter Pattern (Default Adapter Pattern) or Default Adapter Pattern.
    2) When it is not necessary to implement all the methods provided by the interface , you can first design an abstract class to implement the interface, and provide a default implementation (empty method) for each method in the interface , then the subclass of the abstract class can have a choice 3) It is suitable for situations where an interface does not want to use all its methods .
public interface Interface {
    
    
	void m1();
	void m2();
	void m3();
	void m4();
}
public abstract class AbstartAdatper implements Interface {
    
    
	@Override
	public void m1(){
    
    	}
	@Override
	public void m2(){
    
    	}
	@Override
	public void m3(){
    
    	}
	@Override
	public void m4(){
    
    	}
}
public class Client {
    
    

	public static void main(String[] args) {
    
    
		AbstartAdatper aba = new AbstartAdatper(){
    
    
			@Override
			public void m1(){
    
    
				System.out.println("接口适配器");
			}
		};
		aba.m1();
	}
}

2. Bridge mode

3. Decoration mode

4. Combination mode

5. Appearance Mode

6. Flyweight mode

7. Proxy mode

  • Basic introduction to proxy mode
    1), Proxy mode: Provide a stand-in for an object to control access to this object. That is, the target object is accessed through the proxy object. The advantage of this is that on the basis of the realization of the target object, additional functional operations can be enhanced, that is, the function of the target object can be extended.
    2), the object to be proxied can be a remote object, an object with high creation cost, or an object that requires security control 3), there are
    different forms of proxy mode, mainly three kinds of static proxy , dynamic proxy (JDK proxy, interface proxy) and Cglib Proxy (objects can be dynamically created in memory without implementing interfaces, which belong to the category of dynamic proxies).

①, static proxy

  • Basic introduction to static code mode
    When static proxy is used, it is necessary to define an interface or a parent class, and the proxy object (that is, the target object) and the proxy object implement the same interface or inherit the same parent class. Application examples: ➢Specific requirements
    1
    )
    , Define an interface: ITeacherDao
    2), the target object TeacherDAO implements the interface ITeacherDAO
    3), use the static proxy method, you need to implement ITeacherDAO in the proxy object TeacherDAOProxy
    4), call the target object by calling the method of the proxy object when calling.
    5 ), special reminder: the proxy object and the target object must implement the same interface, and then call the method of the target object by calling the same method.

  • Advantages and disadvantages of static proxy
    1), advantages: without modifying the function of the target object, the target function can be extended through the proxy object.
    2), disadvantages: because the proxy object needs to implement the same interface as the target object, there will be many proxies Class
    3), once the method is added to the interface, both the target object and the proxy object must be maintained

public interface ITeacher {
    
    
	void teacher();
}
public class Teacher implements ITeacher{
    
    
	//老师类
	public void teacher() {
    
    
		System.out.println("语文老师原教课内容!");
	}
}
public class TeacherProxy implements ITeacher{
    
    
	
	private ITeacher iTeacher;
	
	TeacherProxy(ITeacher iTeacher){
    
    
		this.iTeacher = iTeacher;
	}
	public void teacher(){
    
    
		System.out.println("新老师擦黑板!");
		iTeacher.teacher();
		System.out.println("下课了,关上门走了!");
	}
}
public class Client {
    
    

	public static void main(String[] args) {
    
    
		new TeacherProxy(new Teacher()).teacher();
	}
}

②, dynamic agent

  • The basic introduction of dynamic proxy mode
    1), the proxy object does not need to implement the interface, but the target object must implement the interface, otherwise the dynamic proxy cannot be used
    2), the generation of the proxy object is to use the JDK API to dynamically build the proxy in memory Object
    3), dynamic proxy is also called: JDK proxy, interface proxy
  • API for generating proxy objects in JDK
    1), proxy class package: java.lang.reflect.Proxy
    2), JDK implements proxy only needs to use newProxyInstance method, but this method needs to receive three parameters, the complete
    writing method is: .
    static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
    • Parameter 1 : loader, class loader, the dynamic proxy class is created at runtime, and any class needs a class loader to load it into memory.
      General situation: current class.class.getClassLoader();
      target class instance.getClass().getInterface();
    • Parameter 2 : Class[] interfaces All interfaces that the proxy class needs to implement
      Method 1: **Target class instance. getClass(). getInterfaces() ;**Note: Only the interface of the parent element can be obtained, not the interface of the parent element
      Method 2: new Class []{UserService.class}
      For example: jdbc driver –> DriverManager gets interface Connection
    • Parameter 3 : InvocationHandler processing class, interface, must implement class, generally use anonymous internal
      to provide invoke method, when each method of proxy class is executed, invoke will be called once
      • Parameter 3.1 : Object proxy: proxy object
      • Parameter 3.2 : Method method: the description object (reflection) of the method currently executed by the proxy object
        Execution method name: method.getName( )
        Execution method: method.invoke(object, actual parameter)
      • Parameter 3.3 : 0bject[] args: method actual parameters
public interface ITeacher {
    
    
	void teacher();
	void mathTea();
}
public class Teacher implements ITeacher{
    
    
	//老师类
	public void teacher() {
    
    
		System.out.println("语文老师原教课内容!");
	}
	public void mathTea(){
    
    
		System.out.println("数学老师原教课内容!");
	}
}
public class ProxyFactory {
    
    

	private ITeacher iTeacher;
	
	ProxyFactory(ITeacher iTeacher){
    
    
		this.iTeacher = iTeacher;
	}
	
	public Object getInstance(){
    
    
	
		return Proxy.newProxyInstance(
				ITeacher.class.getClassLoader(),
				iTeacher.getClass().getInterfaces(), 
				new InvocationHandler() {
    
    
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
    
    
						
						System.out.println("执行老师方法前!");
						Object obj = method.invoke(iTeacher, args);
						System.out.println("当然这句话可以执行其他方法!");
						return obj;
					}
				});
	}
}
public class Client {
    
    

	public static void main(String[] args) {
    
    
		ITeacher iTeacher = (ITeacher)new ProxyFactory(new Teacher()).getInstance();
		iTeacher.mathTea();
		iTeacher.teacher();
	}
}

③, Cglib agent

  • Basic introduction of Cglib proxy mode
    1), Static proxy and JDK proxy mode both require the target object to implement an interface, but sometimes the target object is just a single object and does not implement any interface . At this time, the target object subclass can be used To realize the proxy, this is the Cglib proxy
    2) Cglib proxy is also called a subclass proxy. It builds a subclass object in memory to realize the function extension of the target object. Some books also attribute Cglib proxy to dynamic proxy.
    3), Cglib is a powerful high-performance code generation package, which can extend java classes and implement java interfaces at runtime. It is widely used by many AOP frameworks, such as Spring AOP, to implement method interception 4)
    , How to choose the proxy mode in AOP programming:

     		1. **目标对象需要实现接口,用JDK代理**
                  		2. **目标对象不需要实现接口,用Cglib代理**
    

    5), the bottom layer of the Cglib package is to convert the bytecode and generate new classes by using the bytecode processing framework ASM

The jar package found in Mybatis on April 6, 2020 can also run

asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar

public class TeacherDao {
    
    

	public void teacher(){
    
    
		System.out.println("教书,cglibProxy not need Interface!");
	}
	public void mathTeacher(){
    
    
		System.out.println("Math class.cglibProxy not need Interface!");
	}
}
public class ProxyFactory implements MethodInterceptor{
    
    

	private Object object;
	ProxyFactory(Object Obj){
    
    
		this.object = Obj;
	}
	
	public void setTeacherDao(Object Obj) {
    
    
		this.object = Obj;
	}
	
	public Object getInstance(){
    
    
		//1. 创建一个工具类
		Enhancer enhancer = new Enhancer();
		//2. 拿到他的class,设置它的父类。
		enhancer.setSuperclass(object.getClass());
		//3. 设置回调函数。
		enhancer.setCallback(this);
		//4. 创建子类对象,及代理对象。
		return enhancer.create();
	}

	@Override
	public Object intercept(Object arg0, Method method, Object[] arg2,MethodProxy arg3) throws Throwable {
    
    
							//   未知			方法					形参
		//抽象类底层封装的自动调用 intercept,默认对没个方法都进行了封装
		System.out.println("开始调用Cglib代理对象!");
		Object obj = method.invoke(object, arg2);
		System.out.println("调用代理对象结束。");
		return null;
	}
}
public class Client {
    
    

	public static void main(String[] args) {
    
    
		ProxyFactory proxy = new ProxyFactory(new TeacherDao());
		TeacherDao tea = (TeacherDao)proxy.getInstance();
		tea.mathTeacher();
		tea.teacher();
	}
}

④. Introduction to common agency models

1), firewall proxy.

​ The internal network penetrates the firewall through the proxy to achieve access to the public network.
2), cache proxy

​For example: when requesting resources such as image files, first go to the cache proxy to get them. If the resources are obtained, it is ok. If the resources cannot be obtained, then go to the public network or database to get them, and then cache them.
3), remote agent

​ The local representative of the remote object, through which the remote object can be called as a local object. Remote agents communicate information over the network with real remote objects.

4), synchronization agent: mainly used in multi-threaded programming to complete the synchronization work between multiple threads

3), behavioral model

3) Behavioral patterns: template method pattern, command pattern, visitor pattern, iterator pattern, observer pattern, intermediary pattern, memo pattern, interpreter pattern (Interpreter pattern), state pattern, strategy pattern, responsibility chain pattern ( Chain of Responsibility pattern) .

1. Template method pattern

  • basic introduction.

    1), template method pattern (Template Method Pattern), also known as template pattern (Template Pattern), Z publicly defines the template that executes its method in an abstract class. Its subclasses can override the method implementation as needed, but calls will be made in the manner defined in the abstract class.
    2) To put it simply, the template method pattern defines the skeleton of an algorithm in an operation, and delays some steps to the subclass, so that the subclass can redefine certain aspects of the algorithm without changing the structure of the algorithm 3) This
    type of design pattern is a behavioral pattern.

  • Notes and Details of the Template Method Pattern

    1), the basic idea is: the algorithm only exists in one place, that is, in the parent class , and it is easy to modify. When the algorithm needs to be modified, as long as the template method of the parent class or some steps that have been implemented are modified, the subclass will inherit these modifications
    2), and maximize code reuse. The template method of the parent class and some steps that have been implemented will be inherited by the subclass and used directly.
    3) Not only unifies the algorithm, but also provides great flexibility. The template method of the parent class ensures that the structure of the algorithm remains unchanged, while the implementation of some steps is provided by the subclass.
    4), the shortcomings of this mode: each different implementation needs a subclass implementation, resulting in an increase in the number of classes, making the system even larger 5), general template
    methods are added with the final keyword to prevent subclasses Override the template method.
    6), Template method mode usage scenario: When a process is to be completed, the process needs to perform a series of steps. This series of steps is basically the same, but the individual steps may be different in implementation. Usually consider Use the template method pattern to handle

    Notes and Details of the Template Method Pattern

① Normal template method mode

public abstract class SoyaMilk {
    
    
//final can't writer son class
	final void make(){
    
    
		System.out.println("Making Soya Milk start!");
		select();
		add();
		soak();
		beat();
	}
	abstract void select();
	final void add(){
    
    
		System.out.println("add Make Milk material!");
	}
	final void soak(){
    
    
		System.out.println("soak on the water!");
	}
	final void beat(){
    
    
		System.out.println("beat over finish!");
	}
}
public class Pennut extends SoyaMilk{
    
    
	@Override
	void select() {
    
    
		System.out.println("select big Soya!");
	}
}
public class Client {
    
    

	public static void main(String[] args) {
    
    
		SoyaMilk soyaMilk = new Pennut();
		soyaMilk.make();
	}
}

② Hook method

  • The hook method of the template method pattern.
    1) In the parent class of the template method pattern, we can define a method, which does nothing by default, and subclasses can override it according to the situation. This method is called a "hook".
    2) Let’s use the above example of making soy milk to explain. For example, we also want to make pure soy milk without adding any ingredients . Please use the hook method to modify the previous template method
public abstract class SoyaMilk {
    
    
//final can't writer son class
	final void make(){
    
    
		select();
		if(isPure()){
    
    
			add();
		}
		soak();
		beat();
	}
	abstract void select();
	final void add(){
    
    
		System.out.println("add Make Milk material!");
	}
	final void soak(){
    
    
		System.out.println("soak on the water!");
	}
	final void beat(){
    
    
		System.out.println("beat over finish!");
	}
   //可以设置需要还是不需要调用的方法
	boolean isPure(){
    
    
		return true;
	}
}
public class PureMilk extends SoyaMilk{
    
    
	@Override
	void select() {
    
    
		System.out.println("select big Soya!");
	}
	@Override
	boolean isPure(){
    
    
		return false;
	}
}
public class Client {
    
    

	public static void main(String[] args) {
    
    
		SoyaMilk soyaMilk = new Pennut();
		soyaMilk.make();
		System.out.println("--------------------------");
		SoyaMilk pureMilk = new PureMilk();
		pureMilk.make();
	}
}

2. Command mode

3. Visitor pattern

4. Iterator pattern

5. Observer pattern

6. Mediator pattern

7. Memo Mode

8. Interpreter mode (Interpreter mode)

9. State mode

10. Strategy Pattern

  • Basic introduction
    1), in the strategy pattern (Strategy Pattern), define the algorithm family, encapsulate them separately, so that they can replace each other, this mode makes the change of the algorithm independent of the customer who uses the algorithm 2), this algorithm embodies
    several Design Principles,
  • First, separate the changing code from the unchanged code;
  • Second, programming for interfaces without specific classes (defining strategy interfaces);
  • Third, use more combination/aggregation and less inheritance (clients use strategies through combination).

Strategy mode: Encapsulate the behavioral interface separately, implement the algorithm family, put the behavioral interface object in the superclass, and set the behavioral object in the subclass
. The principle is: separate the changing parts, encapsulate the interface, and program various functions based on the interface. This pattern
allows behavior to change independently of the user of the algorithm

public abstract class Duck {
    
    
	Flybeha flybeha;
	
	Duck(){
    
    
		disPlay();
		quack();
		swim();
	}
	
	abstract void disPlay();
	
	void quack(){
    
    
		System.out.println("鸭子会叫~~~");
	}
	
	void swim(){
    
    
		System.out.println("鸭子会游泳~~~");
	}
	
	void fly(){
    
    
		if(flybeha != null){
    
    
			flybeha.Fly();
		}else{
    
    
			System.out.println("fly failed");
		}
	}
	
	public void setFlybeha(Flybeha flybeha) {
    
    
		this.flybeha = flybeha;
	}
}
public interface Flybeha {
    
    
	//接口里面写上所有鸭子的飞翔能力描述,让子类去实现
	//将来要添加什么鸭子,直接在写个类实现接口就行了
	void Fly();
}
//各种飞翔能力实现类
public class GoodFly implements Flybeha{
    
    

	@Override
	public void Fly() {
    
    
		System.out.println("this a Duck fly very high!");
	}
}
public class NoFly implements Flybeha{
    
    

	@Override
	public void Fly() {
    
    
		System.out.println("该物种不能飞!");
	}
}
public class BadFly implements Flybeha {
    
    

	@Override
	public void Fly() {
    
    
		System.out.println("this Duck fly is bad~");
	}
}
//野鸭
public class WildDuck extends Duck{
    
    
	
	WildDuck(){
    
    
		flybeha = new GoodFly();
	}
	@Override
	void disPlay() {
    
    
		System.out.println("this is a wildDuck");
	}
}
public class ToyDuck extends Duck{
    
    
	//用到的话,改一下实现类就行了,对于扩展比较方便
	ToyDuck(){
    
    
		flybeha = new NoFly();
	}

	@Override
	void disPlay() {
    
    
		System.out.println("this is a ToyDuck");
	}
}

● Notes and details of the strategy pattern

1) The key of the strategy pattern is: analyze the changing part and the unchanged part in the project
2), the core idea of ​​the strategy pattern is: use more combination/aggregation and less inheritance; use behavior class combination instead of behavior inheritance. More flexible
3), embodies the principle of "closed to modification, open to extension", the client does not need to modify the original code to add behavior, just add a strategy (or behavior), avoiding the use of multiple transfer statements (if... else if.else)
4), provides a way to replace the inheritance relationship: the strategy pattern encapsulates the algorithm in an independent Strategy class so that you can change it independently of its Context, making it easy to switch, easy to understand, and easy to expand 5
) , It should be noted that each time a strategy is added, a class must be added. When there are too many strategies, the number of classes will be huge

11. Chain of Responsibility Model (Chain of Responsibility Model),

Guess you like

Origin blog.csdn.net/weixin_44961083/article/details/113700512