编程知识 cdmana.com

[hard core] 23 design patterns to help you write beautiful code gracefully!

Hello everyone , I'm Xiaoyu .

The principle or source code of every technology stack we usually use is more or less related to the concept of design patterns , It can also be said that , Only a better grasp of the design pattern , Our ability to code More normative 、 concise , More efficient .

secondly , Design patterns are mostly based on the experience of our predecessors , Standing on the shoulders of giants , Absorb their experience and lessons , Our way of coding will last longer .

meanwhile , During our interview, too Bonus options , If you can tell the interviewer about the design pattern , The interviewer will certainly look at you with new eyes . In the work , Have a good idea of design patterns , It will also be of great help to the development of the project .

Next , Follow Xiaoyu to see what design patterns we need to know ~

Preface

Generally speaking, design patterns are divided into three categories :

_ Create pattern :_ Factory method model 、 Abstract factory pattern 、 The singleton pattern 、 Builder pattern 、 Archetypal model .

_ Structural mode :_ Adapter pattern 、 Decorator mode 、 The proxy pattern 、 Appearance mode 、 Bridging mode 、 Portfolio model 、 The flyweight pattern .

_ Behavioral patterns :_ The strategy pattern 、 Template method pattern 、 Observer mode 、 Iterative subpattern 、 The chain of responsibility model 、 Command mode 、 Memo mode 、 The state pattern 、 Visitor mode 、 Intermediary model 、 Interpreter mode .

The singleton pattern

Concept

Make sure there is only one instance of a class , and self-instantiation And provide the whole system with this example .

Use scenarios

  • The environment that requires a unique serial number to be generated ;

  • A shared access point or shared data is needed throughout the project , For example, one Web Counters on the page , No need to record every refresh to the database , Use singleton mode to keep the counter value , And make sure it's thread safe ;

  • Creating an object consumes too many resources , To access IO And database resources ;

  • A lot of static constants and static methods need to be defined ( Such as tools ) Environment , You can use the singleton mode ( Of course , It can also be declared directly as static The way ).

Code example

Thread safety :

`public class Singleton {`
 `private static final Singleton singleton = new Singleton();`
 `// Limit the generation of multiple objects `
 `private Singleton(){`
 `}`
 `// Through this method, the instance object is obtained `
 `public static Singleton getSingleton(){`
 `return singleton;`
 `}`
 `// Class , Try to be  static`
 `public static void doSomething(){`
 `}`
`}`

Thread unsafe :

`public class Singleton {`
 `private static Singleton singleton = null;`
 `// Limit the generation of multiple objects `
 `private Singleton(){`
 `}`
 `// Through this method, the instance object is obtained `
 `public static Singleton getSingleton(){`
 `if(singleton == null){`
 `singleton = new Singleton();`
 `}`
 `return singleton;`
 `}`
`}`

Unsafe for threads :

stay getSingleton Methods before adding synchronized keyword , It can also be in getSingleton Add... In the method synchronized To achieve .

Factory mode

Concept

Defines an interface for creating objects , Let the subclass decide which class to instantiate . The factory method makes a class Instantiation delay To its subclasses .

Use scenarios

jdbc Connect to database , Hardware access , Reduce the generation and destruction of objects

structure

_ Simple factory model :_ A module only needs one factory class , There's no need to produce it , Using static methods

_ Multiple factory classes :_ Every race ( Specific product categories ) They all correspond to a Creator , Each creator is responsible for creating the corresponding product object independently , Very consistent with the principle of single responsibility

_ Instead of singleton mode :_ The core requirement of singleton mode is that there is only one object in memory , With the factory method pattern, you can also produce only one object in memory

_ Delay initialization :_ProductFactory Responsible for the creation of product class objects , And through prMap Variable produces a cache , Keep... For objects that need to be reused again

Code example

Product Responsible for defining product commonalities for abstract product classes , Realize the most abstract definition of things ;

Creator Create classes for abstractions , It's the abstract factory , How to create a product class is determined by the implementation factory ConcreteCreator Accomplished .

`public class ConcreteCreator extends Creator {`
 `public <T extends Product> T createProduct(Class<T> c){`
 `Product product=null;`
 `try {`
 `product =`
 `(Product)Class.forName(c.getName()).newInstance();`
 `} catch (Exception e) {`
 `// exception handling `
 `}`
 `return (T)product;`
 `}`
`}`

Abstract factory pattern

Concept

Provides an interface for creating a set of related or interdependent objects , and No need to specify their concrete classes .

Use scenarios

A family of objects ( Or a group of unrelated objects ) All have the same constraints .

When it comes to different operating systems , You can consider using the abstract factory pattern .

Code example

`public abstract class AbstractCreator {`
 `// establish  A  Product family `
 `public abstract AbstractProductA createProductA();`
 `// establish  B  Product family `
 `public abstract AbstractProductB createProductB();`
`}`

Template method pattern

Concept

Define the framework of an algorithm in an operation , Instead, defer some steps to subclasses . So that subclasses can Without changing the structure of an algorithm You can redefine some specific steps of the algorithm .

Use scenarios

  • Multiple subclasses have public methods , And when the logic is basically the same .

  • important 、 Complex algorithms , The core algorithm can be designed as a template method , The peripheral details are implemented by each subclass .

  • Refactoring , Template method pattern is a frequently used pattern , Extract the same code into the parent class , And then through the hook function ( see “ Template method pattern extension ”) Restrain their actions .

structure

Abstract template :AbstractClass For abstract templates , Its methods fall into two categories :

1、 The basic method : It's also called basic operation , Methods implemented by subclasses , And when the template method is called .

2、 Template method : There can be one or more , It's usually a specific method , It's a framework , Realize the scheduling of basic methods , Complete the fixed logic .

Be careful : In order to prevent malicious operation , General template methods add final keyword , Overwriting... Is not allowed .

_ Specific template :_ Implement one or more abstract methods defined by the parent class , That is, the basic methods defined by the parent class are implemented in the child class .

Code example

`package templateMethod;`
`public class TemplateMethodPattern`
`{`
 `public static void main(String[] args)`
 `{`
 `AbstractClass tm=new ConcreteClass();`
 `tm.TemplateMethod();`
 `}`
`}`
`// abstract class `
`abstract class AbstractClass`
`{`
 `public void TemplateMethod() // Template method `
 `{`
 `SpecificMethod();`
 `abstractMethod1();`
 `abstractMethod2();`
 `}`
 `public void SpecificMethod() // The specific methods `
 `{`
 `System.out.println(" Concrete methods in abstract classes are called ...");`
 `}`
 `public abstract void abstractMethod1(); // Abstract method 1`
 `public abstract void abstractMethod2(); // Abstract method 2`
`}`
`// Specific subclass `
`class ConcreteClass extends AbstractClass`
`{`
 `public void abstractMethod1()`
 `{`
 `System.out.println(" Abstract method 1 The implementation of is called ...");`
 `}`
 `public void abstractMethod2()`
 `{`
 `System.out.println(" Abstract method 2 The implementation of is called ...");`
 `}`
`}`

Builder pattern

Concept

Separate the construction of a complex object from its representation , bring The same build process can create different representations .

Use scenarios

  • Same method , Different order of execution , When different event results are produced , You can use builder mode .

  • Multiple components or parts , Can be assembled into an object , But the results are not the same , You can use this mode .

  • The product category is very complex , Or the different calling order in the product class produces different performance , It's a good time to use builder mode .

structure

_Product Product class :_ The template method pattern is usually implemented , There are template methods and basic methods .

_Builder Abstract builder :_ Standardizing the formation of products , It is usually implemented by subclasses .

_ConcreteBuilder Specific builder :_ Implement all methods defined by an abstract class , And return a group created object .

_Director Directors :_ Responsible for arranging the order of existing modules , Then tell Builder Start building

Code example

`public class ConcreteProduct extends Builder {`
 `private Product product = new Product();`
 `// Set up product parts `
 `public void setPart(){`
 `/*`
 `*  Logical processing within the product class `
 `*/`
 `}` 
 `// Build a product `
 `public Product buildProduct() {`
 `return product;`
 `}`
`}`

The proxy pattern

Concept

For other objects Provide a proxy to control Access to this object .

structure

_Subject Abstract theme role :_ Abstract topic classes can be abstract classes or interfaces , Is the most common definition of business type , No special requirements .

_RealSubject Specific subject roles :_ It's also called the delegated role 、 Surrogate role . It's the big loser , Is the concrete executor of business logic .

_Proxy Surrogate subject role :_ It's also called the delegate class 、 proxy class . It's responsible for the application of real characters , Methods that define all abstract topic classes 、 Restrict delegating to real theme role implementations , And do the pre-processing and post-processing work before and after the real theme role processing .

classification

_ General agent :_ In this mode , The caller only knows the agent, not who the real role is , Shielding the influence of real role changes on high-level modules , Real theme characters can be modified as they want , No impact on high-level modules , As long as you implement the method corresponding to the interface , This mode is very suitable for the situation with high scalability requirements .

_ Compulsory agency :_ The concept of mandatory proxy is to find the proxy role from the real role , No direct access to real characters . High level modules just call getProxy You can access all the methods of the real character , It doesn't need to generate a proxy at all , Agent management has been done by real characters themselves .

  • difference : General agency means that we need to know the existence of agency , Then we can visit ; Forcing a proxy means that the caller calls the real role directly , It doesn't matter if the agent exists , The generation of its agent is determined by the real role .

_ A dynamic proxy :_ Generate all methods based on the interface being proxied , That is to say, given an interface , Dynamic agents will claim “ I have implemented all the methods under this interface ”. Two independent development lines . Dynamic agent realizes the responsibility of agent , Business logic realizes the related logic functions , There is no necessary coupling relationship between the two . Notice cuts in from another perspective , Finally, coupling in high-level modules , Complete the task of logic encapsulation .

  • Intention : Cross section programming , Enhance or control the behavior of objects without changing our existing code structure .

  • The first condition : The proxy class must implement an interface .

Code example

`public Object getProxy(@Nullable ClassLoader classLoader) {`
 `if (logger.isTraceEnabled()) {`
 `logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());`
 `}`
 `Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);`
 `findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);`
 `return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);`
`}`

Archetypal model

Concept

Using prototype instances to specify the kind of objects to create , also By copying these prototypes Create a new object .

Use scenarios

_ Resource optimization scenarios :_ Class initialization needs to digest a lot of resources , This resource includes data 、 Hardware resources, etc .

_ Performance and security requirements scenarios :_ adopt new Generating an object requires a lot of data preparation or access rights , You can use prototype mode .

_ A scene where an object has multiple modifiers :_ An object needs to be provided for other objects to access , And each caller may need to change its value , Sure 、 Consider using prototype mode to copy multiple objects for callers to use .

advantage

Prototype pattern is actually implementation Cloneable Interface , rewrite clone() Method .

_ Excellent performance :_ The prototype pattern is a copy of the binary stream in memory , More than direct new The performance of an object is much better , Especially when a large number of objects are generated in a cycle , Prototype pattern can better reflect its advantages .

_ Escape the constraints of constructors :_ This is both its advantage and its disadvantage , Copy directly in memory , Constructors don't execute .

Code example

`public class PrototypeClass implements Cloneable{`
 `// Override parent  Object  Method `
 `@Override`
 `public PrototypeClass clone(){`
 `PrototypeClass prototypeClass = null;`
 `try {`
 `prototypeClass = (PrototypeClass)super.clone();`
 `} catch (CloneNotSupportedException e) {`
 `// exception handling `
 `}`
 `return prototypeClass;`
 `}`
`}`

Intermediary model

Concept

Encapsulating a series of object interactions with a mediation object , Mediators make objects interact without explicit interaction , To make it Loose coupling , And they can change their interaction independently .

Use scenarios

The mediator pattern is suitable for close coupling between multiple objects , The standard of tight coupling is : There is a spider web structure in the class diagram , That is, each class is directly related to other classes .

structure

_Mediator The role of an abstract intermediary :_ Abstract mediator role defines a unified interface , It is used for communication between colleagues' roles .

_Concrete Mediator Specific intermediary role :_ The specific intermediary role realizes cooperative behavior by coordinating the roles of colleagues , So it has to depend on the role of each colleague .

_Colleague Colleague role :_ Every co-worker role knows the intermediary role , And when communicating with other coworker roles , Be sure to collaborate through the intermediary role . There are two types of behavior for each colleague class : One is the behavior of colleagues themselves , Such as changing the state of the object itself , Dealing with your own behavior, etc , This behavior is called spontaneous behavior (SelfMethod), There is no dependency on other colleagues or mediators ; The second is the behavior that must rely on the intermediary to complete , It's called dependency methods (Dep-Method).

Sample code

`public abstract class Mediator {`
 `// Define the colleague class `
 `protected ConcreteColleague1 c1;`
 `protected ConcreteColleague2 c2;`
 `// adopt  getter/setter  Method to inject the colleague class `
 `public ConcreteColleague1 getC1() {`
 `return c1;`
 `}`
 `public void setC1(ConcreteColleague1 c1) {`
 `this.c1 = c1;`
 `}`
 `public ConcreteColleague2 getC2() {`
 `return c2;`
 `}`
 `public void setC2(ConcreteColleague2 c2) {`
 `this.c2 = c2;`
 `}`
 `// The business logic of the mediator model `
 `public abstract void doSomething1();`
 `public abstract void doSomething2();`
`}`

Command mode

Concept

Encapsulate a request as an object , So you can parameterize the client with different requests , Yes Request queuing or request logging , Can provide command undo and restore function .

Use scenarios

Where you think it's a command, you can use command mode , for example , stay GUI In development , The click of a button is a command , You can use command mode ; simulation DOS When ordered , Of course, command mode should also be adopted ; Trigger - Feedback mechanism, etc .

structure

_Receive Receiver role :_ The role is the role of work , The command passed here should be executed , In our example above, it is Group Three implementation classes of ( Demand group , Art Group , Code group ).

_Command Command character :_ All commands that need to be executed are declared here .

_Invoker The role of the caller :_ Received an order , And execute the command . In the example , I ( project manager ) That's the character .

Code example

`public class Invoker {`
 `private Command command;`
 `//  Set value injection `
 `public void setCommand(Command command) {`
 `this.command = command;`
 `}`
 `//  Carry out orders `
 `public void action() {`
 `this.command.execute();`
 `}`
`}`

The chain of responsibility model

Concept

Give multiple objects a chance to process requests , This avoids the coupling between the sender and the receiver of the request . Put these objects In a chain , And pass the request along the chain , Until an object processes it .

duty

The abstract processor implements three responsibilities :

1、 Define the processing method of a request handleMessage, The only way to open up ;

2、 Define a chain arrangement setNext, Set up the next handler ;

3、 It defines two methods that a specific requester must implement : Define the level you can handle getHandlerLevel And specific processing tasks echo.

Code example

`public abstract class Handler {`
 `private Handler nextHandler;`
 `// Every handler has to deal with the request `
 `public final Response handleMessage(Request request){`
 `Response response = null;`
 `// Determine if it's your own processing level `
 `if(this.getHandlerLevel().equals(request.getRequestLevel())){`
 `response = this.echo(request);`
 `}else{ // Not at your own processing level `
 `// Determine if there is a next processor `
 `if(this.nextHandler != null){`
 `response =`
 `this.nextHandler.handleMessage(request);`
 `}else{`
 `// There is no proper handler , The business deals with itself `
 `} }`
 `return response;`
 `}`
 `// Set who the next handler is `
 `public void setNext(Handler _handler){`
 `this.nextHandler = _handler;`
 `}`
 `// Each processor has a processing level `
 `protected abstract Level getHandlerLevel();`
 `// Each processor must implement the processing task `
 `protected abstract Response echo(Request request);`
`}`

matters needing attention

The number of nodes in the chain needs to be controlled , Avoid super long chains , The general practice is to Handler Set a maximum number of nodes in , stay setNext Method to determine whether it has exceeded its threshold , If it exceeds, the chain is not allowed to establish , Avoid unintentional damage to system performance .

Decoration mode

Concept

Dynamically give an object Add some extra responsibilities . In terms of adding functionality , Decoration patterns are more flexible than subclasses .

Use scenarios

  • Need to extend the function of a class , Or add additional functions to a class .

  • You need to dynamically add functionality to an object , These functions can be revoked dynamically .

  • You need to modify or add features to a group of siblings , Of course, the preferred decoration mode .

structure

_Component Abstract component :_Component It's an interface or an abstract class , It's about defining our core object , That is, the most primitive object . In decorative mode , There must be a fundamental 、 At the core 、 The most primitive interface or abstract class ACTS as Component Abstract component .

_ConcreteComponent The specific components :_ConcreteComponent It's the core 、 The most primitive 、 The most basic interface or abstract class implementation , That's what you're going to decorate .

_Decorator To decorate a character :_ It's usually an abstract class , What's the use of it ? Implementing interfaces or abstract methods , It doesn't have to have abstract methods , There must be one of its attributes private Variable pointing to the Component Abstract component .

_ Specific decorative role :_ Two specific decoration categories , You have to put your core 、 ancestral 、 The most basic things are decorated with other things .

Code example

`/**`
 `*  To decorate a character `
 `*/`
`@Data`
`@AllArgsConstructor`
`@NoArgsConstructor`
`@Log`
`class BufferedReader implements Reader{`
 `private  Reader reader;`
 `@Override`
 `public void read() {`
 `reader.read();`
 `}`
 `public void readLine(){`
 `read();`
 `log.info(" And read only one line ");`
 `}`
`}`

The strategy pattern

Concept

Define a set of algorithms , take Every algorithm is encapsulated , And make them interchangeable .

Use scenarios

  • Multiple classes have only slightly different scenarios in algorithm or behavior .

  • The algorithm needs to switch freely .

  • Scenarios that need to mask algorithm rules .

  • The number of specific strategies exceeds 4 individual , You need to consider using hybrid mode

structure

_Context Encapsulate the character :_ It's also called contextual roles , Link between the above and the next packaging role , Shield high-level modules against policies 、 Direct access to the algorithm , Encapsulate possible changes .

_Strategy Abstract strategy roles :_ Strategy 、 The abstraction of algorithm family , Usually interface , Define the methods and properties that each policy or algorithm must have .

_ConcreteStrategy Specific strategic roles :_ Implement operations in abstract strategies , This class contains specific algorithms .

Code example

`public enum Calculator {`
 `// Addition operation `
 `ADD("+"){`
 `public int exec(int a,int b){`
 `return a+b;`
 `}`
 `},`
 `// Subtraction `
 `SUB("-"){`
 `public int exec(int a,int b){`
 `return a - b;`
 `}`
 `};`
 `String value = "";`
 `// Define member value types `
 `private Calculator(String _value){`
 `this.value = _value;`
 `}`
 `// Gets the value of the enumeration member `
 `public String getValue(){`
 `return this.value;`
 `}`
 `// Declare an abstract function `
 `public abstract int exec(int a,int b);`
`}`

Adapter pattern

Concept

Interface of a class Transform to another interface expected by the client , So that the two classes that could not work together due to interface mismatch can work together .

Use scenarios

When you have an incentive to modify an interface that is already in production , The adapter mode is probably the best for you . For example, the system has expanded , You need to use an existing or newly created class , But this class does not conform to the interface of the system , What do I do ? Don't think about using adapter patterns in the detailed design phase , The main scenario is in the extended application .

The class adapter

_Target The target character :_ This role defines what interfaces the other classes are converted to , That's our expected interface .

_Adaptee The source role :_ Who do you want to turn into the target character , This “ who ” That's the source role , It's already there 、 A well-functioning class or object , Through the packaging of the adapter role , It's going to be a brand new 、 Beautiful characters .

_Adapter Adapter role :_ The core role of the adapter pattern , The other two roles are existing roles , The adapter role needs to be newly created , Its duties are very simple : Converts the source role to the target role , How to convert ? By inheritance or class Association .

Object adapter

Don't use multiple inheritance or inheritance , Instead, use direct correlation , Or the way of delegation .

The difference between object adapter and class adapter :

Class adapters are inter class inheritance , An object adapter is a composite relationship of an object , It can also be said to be the association of classes , This is the fundamental difference between the two . In the actual project, the object adapter uses a relatively large number of scenarios .

Code example

`public class Adapter extends Target`
`{`
 `private Adaptee adaptee;`
 `public Adapter(Adaptee adaptee)`
 `{`
 `this.adaptee=adaptee;`
 `}`
 `public void request()`
 `{`
 `adaptee.specificRequest();`
 `}`
`}` 

Iterator pattern

Concept

It provides a way Access elements in a container object , Without exposing the internal details of the object .

structure

_Iterator Abstract iterator :_ Abstract iterators are responsible for defining interfaces to access and traverse elements , And it's basically fixed 3 A way :first() Get the first element ,next() Access the next element ,isDone() Have you visited the bottom (Java be called hasNext() Method ).

_ConcreteIterator Specific iterators :_ The specific iterator role should implement the iterator interface , Complete the traversal of container elements .

_Aggregate Abstract container :_ The container role is responsible for providing an interface to create a specific iterator role , There must be a similar createIterator() This way , stay Java In general iterator() Method .

_Concrete Aggregate Specific containers :_ The concrete container implements the method of container interface definition , Create an object to hold the iterator .

Code example

`/**`
 `*  Specific iterators `
 `*/`
`public class ConcreteIterator<T> implements Iterator<T> {`
 `private List<T> list = new ArrayList<>();`
 `private int cursor = 0;`
 `public boolean hasNext() {`
 `return cursor != list.size();`
 `}`
 `public T next() {`
 `T obj = null;`
 `if (this.hasNext()) {`
 `obj = this.list.get(cursor++);`
 `}`
 `return obj;`
 `}`
`}`

Portfolio model

Concept

Combine objects into a tree structure to represent “ part - whole ” Hierarchical structure , Make the use of single object and composite object consistent .

Use scenarios

  • Maintenance and display part - The whole relationship scenario , Like a tree menu 、 File and folder management .

  • A scenario in which some modules or functions can be separated from the whole .

  • As long as it's a tree structure , Just consider using the composite pattern .

structure

Component Abstract component roles : Define the common methods and properties of the composite objects , You can define some default behaviors or properties .

_Leaf Leaf component :_ Leaf object , There are no other branches under it , The smallest unit of traversal .

_Composite Tree branches :_ Branch object , Its function is to combine branch nodes and leaf nodes to form a tree structure .

Code example

`public class Composite extends Component {`
 `// Component containers `
 `private ArrayList<Component> componentArrayList = new`
 `ArrayList<Component>();`
 `// Add a leaf or branch component `
 `public void add(Component component){`
 `this.componentArrayList.add(component);`
 `}`
 `// Delete a leaf or branch component `
 `public void remove(Component component){`
 `this.componentArrayList.remove(component);`
 `}`
 `// Get all the leaf and branch components under the branch `
 `public ArrayList<Component> getChildren(){`
 `return this.componentArrayList;`
 `}` 
`}`

Observer mode

Concept

Define a one to many dependency between objects , Make every time an object changes state , Then all objects that depend on it will Be notified and automatically updated .

Use scenarios

  • Associated behavior scenarios . It should be noted that , Association behavior is divisible , instead of “ Combine ” Relationship .

  • Event multi-level trigger scenario .

  • Cross system message exchange scenario , Such as the processing mechanism of message queue .

structure

_Subject Observed :_ Define the responsibilities that must be fulfilled by the observed , It has to be able to dynamically increase 、 Cancel the observer . It is usually an abstract class or an implementation class , Only fulfill the duties that must be fulfilled as the observed : Manage the observer and inform the observer .

_Observer The observer :_ After the observer receives the message , That is to say update( Update method ) operation , Process the received information .

_ConcreteSubject The specific observed :_ Define the business logic of the observed , It also defines which events are notified .

_ConcreteObserver Specific observer :_ Each observation has a different processing response after receiving the message , Each observer has its own processing logic .

Code example

`public abstract class Subject {`
 `// Define an array of observers `
 `private Vector<Observer> obsVector = new Vector<Observer>();`
 `// Add an observer `
 `public void addObserver(Observer o){`
 `this.obsVector.add(o);`
 `}`
 `// Delete an observer `
 `public void delObserver(Observer o){`
 `this.obsVector.remove(o);`
 `}`
 `// Notify all observers `
 `public void notifyObservers(){`
 `for(Observer o:this.obsVector){`
 `o.update();`
 `}`
 `}` 
`}`

Facade mode

Concept

The communication between the outside and the inside of a subsystem is required Through a unified object . The facade pattern provides a high-level interface , Makes the subsystem easier to use .

Use scenarios

  • Provide an interface for external access to a complex module or subsystem

  • Subsystem is relatively independent —— The access to the subsystem from the outside world only needs black box operation

  • Prevent the spread of risk from low-level personnel

structure

_Facade The role of the facade :_ The client can call the methods of this role . This role knows all the functions and responsibilities of the subsystem . In general , This role will delegate all requests sent from the client to the corresponding subsystem , In other words, the role has no actual business logic , It's just a delegate class .

_subsystem Subsystem role :_ There can be one or more subsystems at the same time . Each subsystem is not a separate class , It's a collection of classes . The subsystem does not know the presence of facade . For subsystems , Facade is just another client .

Code pattern

`public class Client {`
 `// The subsystem object of the delegate `
 `private A a= new A();`
 `private B b= new B();`
 `private C c= new C();`
 `// Methods of providing external access `
 `public void methodA(){`
 `this.a.doSomething();`
 `}`
 `public void methodB(){`
 `this.b.doSomething();`
 `}`
 `public void methodC(){`
 `this.c.doSomething();`
 `}`
`}`

Memo mode

Concept

Without breaking encapsulation , Capture the internal state of an object , And save the state outside the object . In this way, the object can be restored to the original saved state later .

Use scenarios

  • Relevant state scenarios that need to save and recover data .

  • Provide a rollback (rollback) The operation of .

  • In the replica scenario that needs to be monitored .

  • The transaction management of database connection is the memo mode .

structure

_Originator Initiator role :_ Record the internal state of the current moment , Responsible for defining which States belong to the backup scope , Responsible for creating and restoring memo data .

_Memento Memo role :_ Responsible for the storage Originator The internal state of the originator object , Provide the internal state the sponsor needs when needed .

_Caretaker Memo administrator role :_ Manage memos 、 Keep and provide memos .

Code example

`public class BeanUtils {`
 `// hold  bean  Put all the attributes and values of into  Hashmap  in `
 `public static HashMap<String,Object> backupProp(Object bean){`
 `HashMap<String,Object> result = new`
 `HashMap<String,Object>();`
 `try {`
 `// get  Bean  describe `
 `BeanInfo`
 `beanInfo=Introspector.getBeanInfo(bean.getClass());`
 `// Get the property description `
 `PropertyDescriptor[]`
 `descriptors=beanInfo.getPropertyDescriptors();`
 `// Traverse all properties `
 `for(PropertyDescriptor des:descriptors){`
 `// The attribute name `
 `String fieldName = des.getName();`
 `// Methods to read properties `
 `Method getter = des.getReadMethod();`
 `// Read property values `
 `Object fieldValue=getter.invoke(bean,new`
 `Object[]{});`
 `if(!fieldName.equalsIgnoreCase("class")){`
 `result.put(fieldName, fieldValue);`
 `} } } catch (Exception e) {`
 `// exception handling `
 `}`
 `return result;`
 `}`
 `// hold  HashMap  The value of is returned to  bean  in `
 `public static void restoreProp(Object bean,HashMap<String,Object>`
 `propMap){`
 `try {`
 `// get  Bean  describe `
 `BeanInfo beanInfo =`
 `Introspector.getBeanInfo(bean.getClass());`
 `// Get the property description `
 `PropertyDescriptor[] descriptors =`
 `beanInfo.getPropertyDescriptors();`
 `// Traverse all properties `
 `for(PropertyDescriptor des:descriptors){`
 `// The attribute name `
 `String fieldName = des.getName();`
 `// If you have this property `
 `if(propMap.containsKey(fieldName)){`
 `// The way to write properties `
 `Method setter = des.getWriteMethod();`
 `setter.invoke(bean, new`
 `Object[]{propMap.get(fieldName)});`
 `} } } catch (Exception e) {`
 `// exception handling `
 `System.out.println("shit");`
 `e.printStackTrace();`
 `}`
 `}`
`}`

Visitor mode

Concept

Package some Operations that act on the elements of a data structure , It can define new operations on these elements without changing the data structure .

Use scenarios

  • An object structure contains many class objects , They have different interfaces , And you want to do something with these objects that depends on their specific classes , In other words, it's a situation that can't be competent with iterator mode .

  • Many different and unrelated operations need to be performed on the objects in an object structure , And you want to avoid having these operations “ Pollution ” Classes for these objects .

structure

_Visitor—— Abstract Visitor :_ Abstract class or interface , Declare which elements visitors can access , To be specific to the procedure is visit The parameters of the method define which objects can be accessed .

_ConcreteVisitor—— Specific visitors :_ It affects what visitors do when they visit a class , What are you going to do .

_Element—— Abstract elements :_ Interface or abstract class , State what kind of visitors are allowed to visit , The procedure is through accept Method .

_ConcreteElement—— Specific elements :_ Realization accept Method , Usually visitor.visit(this), Basically, a pattern has been formed .

_ObjectStruture—— The structure of the object :_ The element producer , Generally, it can be accommodated in many different types 、 Containers with different interfaces , Such as List、Set、Map etc. , In the project , This character is rarely abstracted .

Code example

`public class CompensationVisitor implements Visitor {`
 `@Override`
 `public void Visit(Element element) {`
 `// TODO Auto-generated method stub`
 `Employee employee = ((Employee) element);`
 `System.out.println(`
 `employee.getName() + "'s Compensation is " + (employee.getDegree() * employee.getVacationDays() * 10));`
 `}`
`}`

The state pattern

Concept

Be an object When the inner state changes, allow it to change behavior , This object looks like it changed its class .

Use scenarios

  • A scene in which behavior changes as states change , This is also the starting point of the model , For example, permission design , The state of people is different, even if they perform the same behavior, the results will be different , In this case, you need to consider using state patterns .

  • Conditions 、 A substitute for a branch judgment statement

structure

_State—— Abstract state role :_ Interface or abstract class , Responsible for object state definition , And encapsulate the role of the environment to achieve state switching .

_ConcreteState—— Specific status role :_ Each specific state must fulfill two responsibilities : Behavior management of this state and trend state processing , In layman's terms , It's what we have to do in this state , And how this state transitions to other states .

_Context—— Environmental roles :_ Define the interface required by the client , And responsible for the specific state switching .

Code example

`// Abstract state role `
`public abstract class State {`
 `// Define an environmental role , Provide subclass access to `
 `protected Context context;`
 `// Setting up environment roles `
 `public void setContext(Context _context){`
 `this.context = _context;`
 `}`
 `// Behavior 1`
 `public abstract void handle1();`
 `// Behavior 2`
 `public abstract void handle2();`
`}`

Interpreter mode

Concept

Give a language , A representation of the grammar that defines it , And define an interpreter , The interpreter Use this representation to explain sentences in a language .

Use scenarios

  • Recurring problems can use interpreter mode

  • A simple grammar needs to explain the scene

structure

_AbstractExpression—— abstract interpreter :_ The specific interpretation task is completed by each implementation class , The specific interpreter is composed of TerminalExpression and Non-terminalExpression complete .

_TerminalExpression—— Terminator expression :_ Implement the interpretation operations associated with elements in grammar , Usually there is only one terminator expression in an Interpreter pattern , But there are multiple instances , Corresponding to different terminators .

_NonterminalExpression—— Nonterminal expression :_ Each rule in grammar corresponds to a non terminal expression , Nonterminal expressions increase based on the complexity of the logic , In principle, each grammar rule corresponds to a nonterminal expression .

_Context—— Environmental roles :_ In general, it is used to store the specific value corresponding to each terminator in grammar , This information needs to be stored in environmental roles , In many cases, we use Map It's enough to play an environmental role .

Code example

`/**`
 `*  Terminator expression `
 `*/`
`public class TerminalExpression extends AbstractExpression {`
 `@Override`
 `public void interpret(Context ctx) {`
 `//  Implements the interpretation operation associated with the terminator in the grammar rule `
 `}`
`}`
`/**`
 `*  Nonterminal expression `
 `*/`
`public class NonterminalExpression extends AbstractExpression {`
 `@Override`
 `public void interpret(Context ctx) {`
 `//  Implement the interpretation operation associated with the non terminal character in the grammar rule `
 `}`
`}`

The flyweight pattern

Concept

Using shared objects can effectively Supports a large number of fine-grained objects .

Object information is divided into two parts : Internal state (intrinsic) And the external state (extrinsic).

_ Internal state :_ Internal state is the information that an object can share , It is stored inside the enjoy object and does not change with the environment .

_ External state :_ An external state is a token that an object can depend on , It changes with the environment 、 Unshareable state .

Use scenarios

  • There are a large number of similar objects in the system .

  • Fine-grained objects have a similar external state , And the internal state is independent of the environment , That is, the object has no specific identity .

  • Scenarios where a buffer pool is required .

structure

_Flyweight—— Abstract meta roles :_ It is simply an abstract class of a product , An interface or implementation that defines both the external and internal state of an object .

_ConcreteFlyweight—— Specific enjoy yuan role :_ A specific product class , Implement the business of abstract role definition . It's important to note in this role that internal state processing should be environment independent , There shouldn't be an operation that changes the internal state , The external state was also modified , This is absolutely not allowed .

_unsharedConcreteFlyweight—— Shareable role :_ There are no external states or security requirements ( Such as thread safety ) Objects that can't be shared , This object does not normally appear in the Heyuan factory .

_FlyweightFactory—— The flyweight factory :_ The duties are very simple , That is to construct a pool container , It also provides methods to get objects from the pool .

Code example

`public class FlyweightFactory {`
 `// Define a pool container `
 `private static HashMap<String,Flyweight> pool= new`
 `HashMap<String,Flyweight>();`
 `// The flyweight factory `
 `public static Flyweight getFlyweight(String Extrinsic){`
 `// The object that needs to be returned `
 `Flyweight flyweight = null;`
 `// There is no object in the pool `
 `if(pool.containsKey(Extrinsic)){`
 `flyweight = pool.get(Extrinsic);`
 `}else{`
 `// Create a share object based on the external state `
 `flyweight = new ConcreteFlyweight1(Extrinsic);`
 `// Put it in the pool `
 `pool.put(Extrinsic, flyweight);`
 `}`
 `return flyweight;`
 `}`
`}`

Bridge mode

Concept

take Abstraction and implementation decoupling , So that the two can change independently .

Use scenarios

  • Scenarios where inheritance is not expected or applicable

  • Unstable interface or class abstraction

  • Scenarios that require high reusability

structure

_Abstraction—— Abstract character :_ Its main responsibility is to define the behavior of the character , Also save a reference to the implemented role , The role is generally an abstract class .

_Implementor—— Realize the role :_ It's an interface or an abstract class , Define the necessary behaviors and attributes of a character .

_RefinedAbstraction—— Fixed abstract character :_ It refers to the implementation role to modify the abstract role .

_ConcreteImplementor—— Concrete realization role :_ It implements methods and properties defined by interfaces or abstract classes .

Code example

`public abstract class Abstraction {`
 `// Define a reference to an implemented role `
 `private Implementor imp;`
 `// The constraint subclass must implement the constructor `
 `public Abstraction(Implementor _imp){`
 `this.imp = _imp;`
 `}`
 `// Their own behavior and attributes `
 `public void request(){`
 `this.imp.doSomething();`
 `}`
 `// Get realized roles `
 `public Implementor getImp(){`
 `return imp;`
 `}`
`}`

summary

When you're learning design patterns , Don't make it hard , in the final analysis , It's a summary of some generalities . We need to study and work constantly at ordinary times , Take time to understand its underlying principles , In this way, each design pattern can be applied flexibly .

The design pattern is based on the summary of predecessors , A solution to the problems in some scenarios , Design patterns are not formulas , There's no need to memorize every pattern , It's more important to understand it Abstract ideas , And how application design patterns Better problem solving , What can be achieved . There are many theories , But if we want to master it , For our actual development, it will solve many problems .

Of course, we will continue to update about Design principles The content of , It is convenient for you to further understand the design pattern .

版权声明
本文为[Shallow feather technique]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/04/20210408114459338v.html

Scroll to Top