Summary of design pattern: Design pattern is the use of inheritance between classes, interfaces, class aggregation, combination of relations, to achieve a good extension structure
Create a model
Singleton pattern: Method of creating a single instance
In factory mode, the creation of complex objects is left to the factory, and users do not care about the creation process
In the simple factory pattern, the factory creates different objects depending on the values passed in
Factory pattern: The factory is an abstract class, only common functions, personalized factory function implementation, subclass factory implementation
Abstract Factory pattern: Factories and created objects are abstract methods that are implemented by subclasses
Builder mode: Object creation is guided by Derctor, the actual creation is left to the builder, the builder aggregates to Derctor, and the creation process can be modified
Prototype mode: Clone objects using clone technology or deserialization method, that is, created objects will not be modified because of the original object
Behavior pattern: Adapter pattern: Class extensions to desired classes by clients decorator pattern: Enhancements to class-induced functionality It is divided into generic methods and personalized methods. Personalized methods need to be implemented, aggregated into factory classes, which are composed of containers. For the same objects that have been created, only the proxy pattern (thread private pool) is obtained in the container: the function of the original class is extended
Behavior pattern: template pattern; Template methods are abstract methods, and with template implementation methods, subclasses simply implement personalized methods
Observer mode (passively triggered observer) Method of triggering an observer when the observer has a state change
The policy pattern (actively triggered policy) uses the aggregate policy approach directly
Principles of design pattern: 1. Single responsibility principle (different functional modules are implemented by different classes or methods) (purpose: If the program is not very complex, it needs to follow a single principle. 2. Interface isolation principle (each class depends on (uses) the interface, in which the methods must be used. Low-level code interfaces, abstract classes, variables, use interfaces whenever possible (extension of functionality is possible)
3, dependency inversion principle (interface oriented programming, detail depends on abstraction, not abstraction depends on detail, low level depends on high level) three ways of dependenceInterface implementationConstructor implementationSet method implementation 4, Lee’s substitution principle to minimize the rewrite of the parent class, which will reduce the reusability of the program, especially in the scenario of frequent use of polymorphism
The workaround is that subclasses and superclasses inherit from higher parent classes, using dependency, aggregate combinations instead
5, open and close principle (for extension development, for modification closed) new functions try to add new code rather than modify the original code, such as adding new functions, creating new classes, passing in fixed classes, rather than changing fixed classes
6, Demeter’s law of dependence on their own class, the less you know the better, methods as much as possible encapsulated in their own class, other classes simply call as far as possible to avoid direct variables involving other classes
The principle of composite reuse (try to use composite synthesis rather than inheritance directly) is to use set methods, constructor methods, or new instead of inheriting classes
unl Relationships between classes: dependencies (class A uses B, then A depends on B) generalization (inheritance) implementation (interface implementation) association (whether member variables are defined) aggregation (only other classes are declared in a class) divisible composition (other classes are created in a class) indivisible
Classification of design patterns
The purpose of design mode is to improve the maintainability and expansibility of the software system and reduce the code complexity of the system
Singleton pattern, Factory pattern, Abstract Factory pattern, Builder pattern, Prototype pattern, Decorator pattern, Adapter pattern, Bridge pattern, share pattern
The singleton pattern
Hungry (static variable)
Constructor privatized (prevents new) class internally created objects from being exposed to static method getInstance advantage: created at class load time, avoids multi-threading problems, simple implementation disadvantage: class does not have to be loaded only at getInstance time, may waste memory resources
The constructor is privatized to avoid using new methods to create multiple objects, while the class can be called internally to create objects. Static methods are used for exposed methods to ensure that methods of that class are accessible,
Lazy loading uses double checking
Static inner classes implement the singleton pattern
Static inner classes are not loaded when the class is loaded. Instance objects are executed only when methods are used
Scenarios used by the singleton pattern: frequently used objects
The factory pattern
Of simple factory pattern (object created by the factory according to the incoming symbol type) and create different types of factory factory need return object, depending on the type of the incoming this object is frequently modified, the caller is frequently used by multiple places, so that the use of the customer class and factory is low coupling, modify the factory class, You don’t have to modify the client class a lot
Factory model; Compared with the simple factory pattern, factory as an abstract class, only common function, the implementation of specific factory function, to a subclass of the factory, and factory portfolio to the client class crder class, relative to the simple factory pattern, factory pattern are more scalability for the factory, concrete factory implementation function call, (client class abstract classes, with the combination of)
The abstract factory class is an interface that has subclasses to implement. The abstract interface. The Order class aggregates the abstract factory.
Usage scenarios: 1. When you do not know the exact type of object to use. 2
Advantages:
Decouple the specific product from the creator
Consistent with the principle of single responsibility
In line with the open and close principle
public class designermodal{ public static void main(String[] args) { Application2 application2 = new createproductA(); Product product = application2.GetObject(); // Product is polymorphic, although product.method1() is called; , but executes different product.method1() methods depending on the implementation class; }}Copy the code
interface Product {
public void method1();
}
Copy the code
abstract class Application2{ abstract Product creatproduct(); Product GetObject(){ Product product = creatproduct(); return product; }}Copy the code
class createproductA1 extends Application2{ @Override Product creatproduct() { return new productA(); } } class createproductA extends Application2{ @Override Product creatproduct() { return new productB(); } } class productA implements Product{ public void method1(){ System.out.println("method1"); } } class productB implements Product{ public void method1(){ System.out.println("method2"); }}Copy the code
The abstract factory pattern (the factory and the factory methods are interfaces, made up of new requirements, and only need to implement these methods) has the following advantages: 1. It can be determined that the methods obtained from the factory are compatible with each other
2. Avoid tight coupling between client code and production code
3, in line with the principle of single responsibility
4, in line with the open and close principle
public class abstractfactory { public static void main(String[] args) { databaseutil idatabaseutil = new oracleDatabaseUtil(); Iconnection connection = idatabaseutil.getConnection(); connection.connect(); Icommand icommand = idatabaseutil.getIcommand(); icommand.command(); } } interface Iconnection{ void connect(); } interface Icommand{ void command(); } // Abstract factory mode, factory method interface (methods and classes are made up of interfaces) interface databaseutil{Iconnection getConnection(); Icommand getIcommand(); } class MySqlConnection implements Iconnection{ @Override public void connect() { System.out.println("mysql connected."); } } class MySqlCommond implements Icommand{ @Override public void command() { System.out.println("mysql command."); } } class mysqlDatabaseUtil implements databaseutil{ @Override public Iconnection getConnection() { return new MySqlConnection(); } @Override public Icommand getIcommand() { return new MySqlCommond(); } } class oracleconmand implements Icommand{ @Override public void command() { System.out.println("oracleconnect."); } } class oracleconnect implements Iconnection{ @Override public void connect() { System.out.println("oracleconmand"); } } class oracleDatabaseUtil implements databaseutil{ @Override public Iconnection getConnection() { return new oracleconnect(); } @Override public Icommand getIcommand() { return new oracleconmand(); }}Copy the code
Builders mode: (specialconcreateprobuider polymerization to director, director for parameters, internal call specialconcreateprobuider create methods to create objects)
Pros and cons: The user does not need to know the complexity of the creation process
Usage scenario: You can build different things without knowing how to build them. In the process of building a map, the user delegates the Director class to build objects
Object creation is more complex, specialconcreateprobuider (object) is responsible for creating need individualized need to create the initializer director (responsible for incoming parameters) can share, know the object creation
Advantages: Independent builder, easy to expand
The difference between the factory method and the builder method: Both aim to create a complex object. The factory mode focuses on the whole object creation method, while the builder mode focuses on the object creation process, which can be invoked freely at creation time.
package main.java; public class productModel { public static void main(String[] args) { productbuilder specialconcreateprobuider = new specialconcreateprobuider(); Director director = new Director(specialconcreateprobuider); product product = director.makeProductor("aa", "bb", "cc", "dd", "ee", "ee"); System.out.println(product); } } class Director{ private productbuilder builder; public Director(productbuilder builder) { this.builder = builder; } public product makeProductor(String productname, String productcompany, String part1, String part2, String part3, String part4){ builder.builderProductcompany(productname); builder.builderProductname(productcompany); builder.builderProductpart1(part1); builder.builderProductpart2(part2); builder.builderProductpart3(part3); builder.builderProductpart4(part4); product build = builder.build(); return build; } } interface productbuilder{ void builderProductname(String Productname); void builderProductcompany(String Productcompany); void builderProductpart1(String part1); void builderProductpart2(String part2); void builderProductpart3(String part3); void builderProductpart4(String part4); product build(); } class defualtconcreateprobuider implements productbuilder{ private String Productname; private String Productcompany; private String part1; private String part2; private String part3; private String part4; @Override public void builderProductname( String Productname ) { this.Productname =Productname; } @Override public void builderProductcompany( String Productcompany) { this.Productcompany =Productcompany; } @Override public void builderProductpart1(String part1) { this.part1 = part1; } @Override public void builderProductpart2(String part2) { this.part2 = part2; } @Override public void builderProductpart3(String part3) { this.part3 = part3; } @Override public void builderProductpart4(String part4) { this.part4 = part4; } @Override public product build() { return new product(this.Productname,this.Productcompany,this.part1,this.part2 ,this.part3, this.part4); } } class specialconcreateprobuider implements productbuilder{ private String Productname; private String Productcompany; private String part1; private String part2; private String part3; private String part4; @Override public void builderProductname( String Productname ) { this.Productname =Productname; } @Override public void builderProductcompany( String Productcompany) { this.Productcompany =Productcompany; } @Override public void builderProductpart1(String part1) { this.part1 = part1; } @Override public void builderProductpart2(String part2) { this.part2 = part2; } @Override public void builderProductpart3(String part3) { this.part3 = part3; } @Override public void builderProductpart4(String part4) { this.part4 = part4; } @Override public product build() { return new product(this.Productname,this.Productcompany,this.part1,this.part2 ,this.part3, this.part4); } } class product{ private String Productname; private String Productcompany; private String part1; private String part2; private String part3; private String part4; public product() { } public product(String productname, String productcompany, String part1, String part2, String part3, String part4) { Productname = productname; Productcompany = productcompany; this.part1 = part1; this.part2 = part2; this.part3 = part3; this.part4 = part4; }}Copy the code
Constructor mode 2 Product2 class Builder() static class insert values, static methods. Perform create
Application Scenarios:
The object that needs to be generated has a complex internal structure and the internal properties of the object that need to be generated themselves depend on each other to work with immutable objects
package main.java; public class productModel2 { public static void main(String[] args) { product2 bulid = new product2.Builder().Productname("aa").part1("bb").bulid(); System.out.println(bulid); } } class product2 { private final String Productname; private final String Productcompany; private final String part1; private final String part2; private final String part3; private final String part4; static class Builder{ private String Productname; private String Productcompany; private String part1; private String part2; private String part3; private String part4; public Builder Productname(String productname) { this.Productname = Productname; return this; } public Builder part1(String part1) { this.part1 = part1; return this; } public Builder part2(String part2) { this.part2 = part2; return this; } public Builder part3(String part3) { this.part3 = part3; return this; } public Builder part4(String part4) { this.part4 = part4; return this; } product2 bulid(){ return new product2(this.Productname,this.Productcompany,this.part1,this.part2,this.part3,this.part4); } } public product2(String productname, String productcompany, String part1, String part2, String part3, String part4) { Productname = productname; Productcompany = productcompany; this.part1 = part1; this.part2 = part2; this.part3 = part3; this.part4 = part4; } @Override public String toString() { return "product2{" + "Productname='" + Productname + '\'' + ", Productcompany='" + Productcompany + '\'' + ", part1='" + part1 + '\'' + ", part2='" + part2 + '\'' + ", part3='" + part3 + '\'' + ", part4='" + part4 + '\'' + '}'; }}Copy the code
Prototype mode (the purpose is to copy the prototype object, but the copied object is independent of the original object, i.e. the reference object is different, when modifying the copied object, the original object will not change)
Prototype instances specify the types of objects to be created, and create new objects by copying them (shallow copies are required if they are mutable or primitive data types, such as String). If there is a mutable object in an object, the object needs to be deep-copied.)Shallow copy: refers only to PointersDeep copy: Copies an object
The clone method and serialization method are implemented
Clone is the use of Java clone, a copy of the object
Serialization is the output and input of the object, and the pointer is assigned to the current value for deep copy
Serialization method
Clone method
product3 clone = (product3) super.clone();
BaseInfo clone1 = (BaseInfo) this.baseInfo.clone();
clone.setBaseInfo(clone1);
Copy the code
package main.java;
public class yxms {
public static void main(String[] args) throws CloneNotSupportedException {
BaseInfo gg = new BaseInfo("gg");
product3 product3 = new product3("a", "b", "c", "d", "e", "f",gg);
product3 clone = product3.clone();
clone.getBaseInfo().setCompanyname("aaaaaa");
clone.setPart1("bbbbbbbbbbbbbbbb");
System.out.println(product3);
System.out.println(clone);
}
}
class BaseInfo implements Cloneable{
private String companyname;
public BaseInfo(String companyname) {
this.companyname = companyname;
}
public String getCompanyname() {
return companyname;
}
public void setCompanyname(String companyname) {
this.companyname = companyname;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return super.hashCode()+"BaseInfo{" +
"companyname='" + companyname + '\'' +
'}';
}
}
class product3 implements Cloneable{
private String Productname;
private String Productcompany;
private String part1;
private String part2;
private String part3;
private String part4;
private BaseInfo baseInfo;
public BaseInfo getBaseInfo() {
return baseInfo;
}
public void setBaseInfo(BaseInfo baseInfo) {
this.baseInfo = baseInfo;
}
public String getProductname() {
return Productname;
}
public String getProductcompany() {
return Productcompany;
}
public String getPart1() {
return part1;
}
public String getPart2() {
return part2;
}
public String getPart3() {
return part3;
}
public String getPart4() {
return part4;
}
public product3() {
}
public void setProductname(String productname) {
Productname = productname;
}
public void setProductcompany(String productcompany) {
Productcompany = productcompany;
}
public void setPart1(String part1) {
this.part1 = part1;
}
public void setPart2(String part2) {
this.part2 = part2;
}
public void setPart3(String part3) {
this.part3 = part3;
}
public void setPart4(String part4) {
this.part4 = part4;
}
@Override
protected product3 clone() throws CloneNotSupportedException {
product3 clone = (product3) super.clone();
BaseInfo clone1 = (BaseInfo) this.baseInfo.clone();
clone.setBaseInfo(clone1);
return clone;
}
public product3(String productname, String productcompany, String part1, String part2, String part3, String part4,BaseInfo baseInfo) {
Productname = productname;
Productcompany = productcompany;
this.part1 = part1;
this.part2 = part2;
this.part3 = part3;
this.part4 = part4;
this.baseInfo = baseInfo;
}
@Override
public String toString() {
return super.hashCode()+"product3{" +
"Productname='" + Productname + '\'' +
", Productcompany='" + Productcompany + '\'' +
", part1='" + part1 + '\'' +
", part2='" + part2 + '\'' +
", part3='" + part3 + '\'' +
", part4='" + part4 + '\'' +
", baseInfo=" + baseInfo +
'}';
}
}
Copy the code
Share mode: the actual String, pool technology is used to consolidate the common features of the same code instance (if not, create, if yes, use the original) all share elements will be stored in a container.Figure shows:
Flyweight: abstract class, abstract class of products, at the same time defines the public methods of the abstract * (internal state) and the method of individuation (external) interface or implementation concreatFlyweight: the realizing methods of the flyweight unsharedConcretaFlyweight: The flyweightFactory method implements personalization: a meta-factory class that builds pool containers (collections) and provides methods to get objects from the pool
Implementation of the description: websiteFactory responsible for building pool container (set), at the same time provide the method of object from the pool to get unsharedConcretaFlyweight = user concreatFlyweight = website
public class xyms { public static void main(String[] args) { websiteFactory websiteFactory = new websiteFactory(); Website website = websiteFactory. Getwebsitecatory (" news "); Website website2 = websiteFactory. Getwebsitecatory (" 2 "); website.use(new user("nbb")); website2.use(new user("nxx")); System.out.println(websiteFactory.getpoolsize()); } } class user{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public user(String name) { this.name = name; } @Override public String toString() { return "user{" + "name='" + name + '\'' + '}'; } } abstract class website{ abstract public void use(user a); } class Concreatwebsite extends website{ private String type=""; public Concreatwebsite(String type) { this.type = type; } @Override public void use(user a) { System.out.println("Concreatwebsite"+type+a); Class websiteFactory{private HashMap<String,website> pool = new HashMap<>(); Public website getWebsitecatory (String type){if(! pool.containsKey(type)){ pool.put(type,new Concreatwebsite(type)); } return pool.get(type); } public int getPoolSize (){return pool.size(); }}Copy the code
Integer implementation of the meta schema
Facade pattern: Reduces the complexity of using classes 1, 2, and 3 to implement a function. Facade pattern uses a facade to manage the classes below, and the client only needs to look at the facade, not the implementation classes inside
Advantages: The client does not need to connect the complex calls at the bottom, reducing the complexity of starting services
public class mmmshi { public static void main(String[] args) { facades facades = new facades(); facades.dosomething(); } } class facades{ subsystem1 subsystem = new subsystem1(); subsystem2 subsystemb = new subsystem2(); subsystem3 subsystemc = new subsystem3(); public void dosomething(){ subsystem.method1(); subsystemb.method1(); subsystemc.method1(); } } class subsystem1{ public void method1(){ System.out.println("method1"); } } class subsystem2{ public void method1(){ System.out.println("method2"); } } class subsystem3{ public void method1(){ System.out.println("method3"); }}Copy the code
Adapter pattern :(enhancements to existing classes (aggregated into adapters, enabling extensions to functionality))
Object is configuration mode: implementation method, adapter adpter to get the object adaptee, after processing, output
Usage scenarios: 1. Use the adapter pattern when you want to use some existing classes whose interfaces are incompatible with other code
2. Use this pattern when you want to reuse several existing subclasses that lack common functionality that cannot be added to the superclass
Object adapter pattern
public class adapter1 { public static void main(String[] args) { Target adapter = new Adapter(new adaptee()); int i = adapter.output5v(); System.out.println(i); } } class adaptee{ public int output220(){ return 220; } } interface Target{ int output5v(); } class Adapter implements Target{ private adaptee aa; public Adapter(adaptee aa) { this.aa = aa; } @Override public int output5v() { int i = aa.output220(); // match I return i-100; }}Copy the code
Inheriting the implementation adapter pattern (the adapter inherits the Adapee, exposing the shortcomings of other methods)
Decorator pattern: Attaches functionality to an object without modifying the source object
Implementation method:
Define the standard abstract class Component. The existing functionality inherits the abstract class
Decorators inherit from Component, constructors pass in the Component class, and concreaderector is an option for multi-function enhancements
Component: Extract decorator
Decoretor: Decorator class, which contains objects to be decorated. Because decorator and decorator inherit from the same abstract class, there is no effect on external code. Through decorator, you can modify the property values of the decorator
Advantages and disadvantages: You can extend the functionality of an object without modifying an existing object or creating a subclass of the object. You can dynamically add or delete multiple extension functions. You can extend different decorators to solve the problem of extending different functions. Disadvantages: Multi-layer decoration will be more complex, and it is impossible to control the order of decoration
The difference between the Decorator Pattern and the adapter Pattern: The Decorator Pattern is a structural Pattern that attaches functionality to an object without changing the original object, providing a more flexible alternative to inheritance (extending the functionality of the original object). Used to extend the functionality of a class or add additional responsibilities to a class. 2. Add functions to an object dynamically, which can be undone dynamically.
Adapter Pattern refers to the transformation of an interface of a class into another interface expected by the customer, so that classes incompatible with the original interface can work together. It belongs to the structural design Pattern.
package main.java.sjms; public class decoreationtest1 { public static void main(String[] args) { Drink coffeB = new Chocolate(new Chocolate(new Milke(new CoffeB()))); System.out.println(coffeB.des()); System.out.println(coffeB.cost()); } } abstract class Drink{ private float price; public String des; public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } public String getDes() { return des; } public void setDes(String des) { this.des = des; } public abstract float cost(); public abstract String des(); } class Coffe extends Drink{ @Override public float cost() { return super.getPrice(); } @Override public String des() { return super.getDes(); }} class CoffeB extends Coffe{public CoffeB() {setPrice(1.0f); SetDes (" black card "); }} class CoffeC extends Coffe{public CoffeC() {setPrice(1.0f); SetDes (" white card "); }} class CoffeD extends Coffe{public CoffeD() {setPrice(1.0f); SetDes (" aa "); } } class Decorator extends Drink{ private Drink obj; public Decorator(Drink obj) { this.obj = obj; } public float cost() { return obj.cost()+super.getPrice(); } @Override public String des() { return super.getDes()+"%%"+obj.des() ; } } class Chocolate extends Decorator{ public Chocolate(Drink obj) { super(obj); SetDes (" chocolate "); SetPrice (1.0 f); } } class Milke extends Decorator{ public Milke(Drink obj) { super(obj); setDes("Milke"); SetPrice (1.0 f); } } class doujain extends Decorator{ public doujain(Drink obj) { super(obj); setDes("doujain"); SetPrice (1.0 f); }}Copy the code
implementation
Bridge mode (two groups of classes, so that the classes of one group provide aggregation to the other group, preventing class explosion)
Usage scenario: Suitable for two groups of classes will be frequently added, there are dependencies between each other
Problem: In the case shown below, because each open form of the collection will add new features to the phones, and also add a series of phones, there will be class explosion
The design structure of the above figure 1 is replaced by that of Figure 2, so that the model and brand of mobile phone can be reused
It is implemented by aggregating different brands into different models of mobile phones
Proxy mode:
Static proxy (aggregating classes into a proxy class that processes the aggregated class method before and after it executes)
Dynamic proxy; The constructor is used to inject the implemented class into the proxy’s class, whose implementation calls the proxy. NewProxyInstance implements the proxy method on an object.
Dynamic proxy factory, the following method is JDK’s own proxy method, the target method passed in, in the creation of a factory, instance object passed into the factory, call the factory method, you can achieve dynamic proxy
Cglib generation (inherit the MethidInterceptor class and implement the Intercepter method to perform the proxy on the target proxy object in getProxyInstance) Final classes cannot be propped, and static methods that target methods are static will not be propped
Difference: The JDK’s proxy implementation uses reflection to instantiate proxy objects in conjunction with the classloader. Cglib uses ASM to convert bytecode to generate new classes
The (frequently used) template method pattern (template methods are implemented in abstract classes, used in concrete ways, and implemented by inherited subclasses) avoids the need to write duplicate code when calling methods that use the parent class for template methods and that use the subclass for custom methods
Template methods are put into hook methods, and empty methods are designed to be implemented by subclasses. If they are not implemented, they are not executed
The principle of implementation: inherit template method, need to implement the class by the subclass implementation
The purpose of an empty method is for subclasses to override it
Observer pattern (triggered by the observed action, passively triggered) : Subject relies on multiple Observer instances. Weatherdata registers all ObservCE implementation classes through interface Observer data
Implementation principle: The observed aggregates subscribers, the observed has the function of registering, deleting, and notifying (call the registered class method).
Implementation: the observer class aggregation to be observed in the array of classes, if the observed class to execute the updated method, call the aggregation class display data method, realize the observation of data changes, while the observer has the function of removing the registered class
Usage scenario: Publish and subscribe
Policy mode :(method of directly triggering policies, active triggering) policies are passed to the principal by aggregation (used in dubbo’s policy transformation)
Implement methods: By aggregating the classes of methods that need to be executed into the current class and invoking methods (i.e., policies) in the current class
Scenario :(free toggle method of a class) (toggle method in another class, pass in the object via aggregation, and execute the method internally)
Responsibility chain mode: Usage scenario: when the processing of a request needs to be carried out in different functional areas according to different situations, you can use this responsibility chain mode to design the program
Methods used
The following Approver is a handler: (1) It has an Approper attribute that the next handler can rely on; (2) it has an abstract method that can handle the request
The implementation subclass writes the specific request handling method, and if it cannot handle it, executes the dependent implementation subclass
In the actual call, depending on the order, the implementation subclasses are relied on