Hi, I’m Koba.

The principle or source code of every stack we usually use is more or less related to the concept of design pattern, it can also be said that only a better grasp of the design pattern, our code can be more standardized, concise, and more efficient.

Secondly, most design patterns are repeatedly summarized by our predecessors. Only by standing on the shoulders of giants and absorbing their experience and lessons can we go on a longer path of coding.

At the same time, in our interview process is also a bonus option, if you can explain the design model to the interviewer, the interviewer will be impressed by you. In the work, have a good idea of design pattern, for the development of the project will also be of great help.

Let’s take a look at some of the design patterns we need to know

preface

Generally speaking, design patterns can be divided into three categories:

Creative patterns: Factory method pattern, Abstract factory pattern, singleton pattern, Builder pattern, prototype pattern.

Structural mode: adapter mode, decorator mode, agent mode, appearance mode, bridge mode, composite mode, share mode.

Behavioral patterns: Policy pattern, template method pattern, observer pattern, iteration subpattern, chain of responsibility pattern, command pattern, memo pattern, state pattern, visitor pattern, mediator pattern, interpreter pattern.

The singleton pattern

concept

Ensure that there is only one instance of a class, and that you instantiate it yourself and make it available to the entire system.

Usage scenarios

  • An environment that requires a unique sequence number to be generated;

  • A shared access point or shared data is needed throughout the project, such as a counter on a Web page, which can be saved from logging every refresh to the database, using a singleton pattern to keep the value of the counter and ensure that it is thread-safe;

  • Creating an object consumes too many resources, such as accessing IO and database resources.

  • Environments where you need to define a large number of static constants and static methods (such as utility classes) can use the singleton pattern (or, of course, declare it static).

Code sample

Thread safety:

public class Singleton {
    private static final Singleton singleton = new Singleton();
    // Restrict the generation of multiple objects
    private Singleton(a){}// Use this method to get the instance object
    public static Singleton getSingleton(a){
        return singleton;
    }
    // All other methods in the class should be static
    public static void doSomething(a){}}Copy the code

Thread unsafe:

public class Singleton { private static Singleton singleton = null; Private Singleton getSingleton(){} Public static Singleton getSingleton(){if(Singleton == null){Singleton  = new Singleton(); } return singleton; }}Copy the code

For thread insecurity: use the synchronized keyword in front of the getSingleton method, or use synchronized in the getSingleton method.

The factory pattern

concept

Define an interface for creating objects and let subclasses decide which class to instantiate. The factory method delays the instantiation of a class to its subclasses.

Usage scenarios

JDBC connection to the database, hardware access, reduced object generation and destruction

structure

Simple factory pattern: a module needs only one factory class, there is no need to generate it, using static methods

Multiple factory classes: There is a creator for each race (specific product class), and each creator is independently responsible for creating the corresponding product object, very much in line with the single responsibility principle

Instead of the singleton pattern: The core requirement of the singleton pattern is to have only one object in memory. It is also possible to produce only one object in memory through the factory method pattern

Lazy initialization: ProductFactory is responsible for the creation of product-class objects and generates a cache through the prMap variable that is reserved for objects that need to be reused again

Code sample

Product is responsible for defining the commonness of products and realizing the most abstract definition of things.

Creator creates classes for abstractions, also known as abstract factories, and how to create product classes is done by the concrete implementation factory ConcreteCreator.

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) {return (T)product; }}Copy the code

Abstract Factory pattern

concept

Provides an interface for creating a set of related or interdependent objects without specifying their concrete classes.

Usage scenarios

A family of objects (or a group of unrelated objects) all have the same constraints.

Consider using the abstract factory pattern for any operating system.

Code sample

Public abstract class AbstractCreator {public abstract AbstractProductA createProductA(); Public abstract AbstractProductB createProductB(); }Copy the code

Template method pattern

concept

A framework that defines an algorithm in an operation, deferring some steps to subclasses. Allows subclasses to redefine specific steps of an algorithm without changing its structure.

Usage scenarios

  • Multiple subclasses have common methods and basically the same logic.

  • For important and complex algorithms, the core algorithm can be designed as a template method, and the surrounding details are implemented by each subclass.

  • In refactoring, the template method pattern is a frequently used pattern that extracts the same code into a parent class and then constrains its behavior with hook functions.

structure

Abstract templates: AbstractClass is an abstract template with two classes of methods:

Basic methods: Also called basic operations, are methods implemented by subclasses and called in template methods.

2, template method: there can be one or several, generally a specific method, that is, a framework to achieve the basic method scheduling, complete fixed logic.

Note: To prevent malicious manipulation, the final keyword is added to normal template methods and cannot be overwritten.

Concrete template: Implements one or more abstract methods defined by the superclass, that is, the basic methods defined by the superclass are implemented in the subclass.

Code sample

package templateMethod; public class TemplateMethodPattern { public static void main(String[] args) { AbstractClass tm=new ConcreteClass(); tm.TemplateMethod(); }} public void TemplateMethod() {SpecificMethod(); abstractMethod1(); abstractMethod2(); } public void SpecificMethod() // specific methods {system.out.println (" Specific methods are called in abstract classes..." ); } public abstract void abstractMethod1(); Public abstract void abstractMethod2(); Class ConcreteClass extends AbstractClass {public void abstractMethod1() { System.out.println(" The implementation of abstract method 1 is called..." ); } public void abstractMethod2() {system.out.println (" implementation of abstractMethod2 is called..." ); }}Copy the code

Builder model

concept

Separating the construction of a complex object from its representation allows the same construction process to create different representations.

Usage scenarios

  • The Builder pattern can be used when the same method, with different execution sequences, produces different event results.

  • This pattern can be used when multiple parts or parts can be assembled into an object but produce different results.

  • The Builder pattern is appropriate when the product class is very complex, or when the order of calls in the product class results in different performance.

structure

Product Class: Usually implements the template method pattern, that is, there are template methods and base methods.

Builder abstract Builder: A specification of the building of a product, typically implemented by subclasses.

ConcreteBuilder: Implements all methods defined by an abstract class and returns a constructed object.

The Director class: is responsible for ordering the existing modules and then telling the Builder to start building

Code sample

public class ConcreteProduct extends Builder { private Product product = new Product(); Public void setPart(){public Product buildProduct() {return Product; }}Copy the code

The proxy pattern

concept

Provide a proxy for other objects to control access to that object.

structure

Subject Abstract topic role: An abstract topic class can be an abstract class or an interface. It is a common business type definition and has no special requirements.

RealSubject Specific subject roles: also known as delegated roles or agent roles. It is the sucker, the enforcer of business logic.

Proxy Proxy topic role: also called a delegate class or a Proxy class. It is responsible for the application of the real role, delegating all the methods and restrictions defined by the abstract topic class to the implementation of the real topic role, and doing pre-processing and post-processing work before and after the real topic role is processed.

classification

General agent: in this mode, the caller know agent only and don’t know who is the real role, block the effects of the change in the real role of high-level modules, the theme of the true character can modify how think to modify, to the high-level modules do not have any influence, as long as you have corresponding method implements an interface, the model is very suitable for requiring higher extensibility.

Forced proxy: The concept of forced proxy is to search for the proxy role from the real role. Direct access to the real role is not allowed. The high-level module simply calls getProxy to access all the methods of the real role. It does not need to generate a proxy at all. The management of the proxy is done by the real role itself.

  • The difference: normal proxy is that we need to know the existence of proxy, which is similar to the GamePlayerProxy class existence, and then access; A forced proxy is one in which the caller invokes the real role directly, regardless of whether the proxy exists or not. The proxy generation is determined by the real role.

Dynamic proxy: Generates all methods based on the proxied interface, that is, given an interface, the dynamic proxy declares “I have implemented all methods on that interface”. Two lines of independent development. The dynamic proxy implements the responsibilities of the proxy, and the business logic Subject implements the related logical functions. There is no necessary coupling between the two. Advice starts at another level and is eventually coupled to a higher-level module, the Client, to encapsulate the logic.

  • Intent: Cross-sectional programming to enhance or control the behavior of objects without changing the structure of our existing code.

  • First requirement: The proxied class must implement an interface.

Code sample

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); }Copy the code

The prototype pattern

concept

Specify what kind of objects to create with prototype instances, and create new objects by copying these prototypes.

Usage scenarios

Resource optimization scenario: Class initialization needs to digest a lot of resources, including data, hardware resources, and so on.

Scenarios with performance and security requirements: If generating an object through New requires very cumbersome data preparation or access rights, the prototype pattern can be used.

Multiple modifiers for an object: when an object needs to be made available to other objects, and each caller may need to modify its value, you can consider using the prototype pattern to copy multiple objects for use by the caller.

advantages

The prototype pattern essentially implements the Cloneable interface and overrides the Clone () method.

Good performance: The prototype pattern is a copy of the binary stream in memory and performs much better than simply new an object, especially when creating a large number of objects in a loop.

Escape from the constructor: this is both a strength and a weakness, as the constructor will not execute when copied directly in memory.

Code sample

Public class PrototypeClass implements Cloneable{@override public PrototypeClass clone(){ PrototypeClass prototypeClass = null; try { prototypeClass = (PrototypeClass)super.clone(); } the catch (CloneNotSupportedException e) {/ / exception handling} return prototypeClass; }}Copy the code

The mediator pattern

concept

By encapsulating a set of object interactions with a mediation object, the mediator loosens the coupling by allowing objects to interact without explicitly, and can change their interactions independently.

Usage scenarios

The mediator pattern applies to situations where multiple objects are tightly coupled, as defined by the presence of a spider web in a class diagram, where each class is directly related to the others.

structure

Mediator Abstracts the Mediator role: The abstract Mediator role defines a unified interface for communication between colleague roles.

Concrete Mediator role: The Concrete Mediator role achieves cooperative behavior by coordinating various colleague roles, so it must rely on each colleague role.

A Colleague role: Each Colleague role knows the mediator role and is sure to collaborate through the mediator role when communicating with other Colleague roles. The behaviors of each colleague class are divided into two types: one is the behavior of the colleague itself, such as changing the state of the object itself and dealing with its own behavior, which is called SelfMethod and has no dependence on other colleague classes or intermediaries. The second type of behavior is one that must rely on an intermediary to complete, called a dep-method.

The sample code

Public Void ConcreteColleague1 public void ConcreteColleague1 public void ConcreteColleague1 public void ConcreteColleague1 public void ConcreteColleague1 public void ConcreteColleague1 protected ConcreteColleague2 c2; 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 pattern public abstract void doSomething1(); public abstract void doSomething2(); }Copy the code

Command mode

concept

Encapsulating a request as an object allows you to parameterize clients with different requests, queue requests or log requests, and provide command undo and recovery capabilities.

Usage scenarios

Command mode can be used where it is considered a command. For example, in GUI development, a button click is a command and command mode can be used. When simulating DOS commands, of course, you should also use command mode; Trigger – feedback mechanism processing and so on.

structure

Receive receiver role: This role is the role that does the work, where commands are passed to be executed, specifically the three implementation classes of the Group (requirements Group, art Group, code Group) in our example above.

Command Command role: All commands to be executed are declared here.

Invoker caller role: Receives commands and executes them. In this example, I (the project manager) am this role.

Code sample

public class Invoker { private Command command; Public void setCommand(Command Command) {this.mand = Command; This.man.execute (); this.man.execute (); this.man.execute (); this.man.execute (); this.man.execute (); this.man.execute (). }}Copy the code

Chain of Responsibility model

concept

This avoids coupling between the sender and receiver of the request by giving multiple objects the opportunity to process the request. Connect the objects into a chain and pass the request along the chain until an object handles it.

Duties and responsibilities

Abstract handlers perform three duties:

1. Define a request handler, handleMessage, which is the only method open to the outside world;

2, define a chain choreography method setNext, set the next handler;

3. Defines two methods that the specific requester must implement: getHandlerLevel, which defines the level it can handle, and echo, which defines the specific processing task.

Code sample

public abstract class Handler { private Handler nextHandler; Public final Response handleMessage(Request Request){Response Response = null; If (this.gethandlerLevel ().equals(request.getrequestLevel ())){response = this.echo(request); If (this.nexthandler!) {this.nexthandler! = null){ response = this.nextHandler.handleMessage(request); }else{// Without a proper handler, the business handles itself}} return response; } public void setNext(Handler _handler){this.nexthandler = _handler; } // Each handler has a processing Level protected abstract Level getHandlerLevel(); // Each handler must implement the processing task. }Copy the code

Matters needing attention

The number of nodes in the chain needs to be controlled to avoid excessively long chains. The general approach is to set a maximum number of nodes in Handler and determine whether the threshold has been exceeded in setNext method. If the threshold is exceeded, the chain is not allowed to be established to avoid unintentionally damaging system performance.

Decorative pattern

concept

Add some extra responsibilities to an object dynamically. Decorator patterns are more flexible in terms of adding functionality than subclassing.

Usage scenarios

  • You need to extend the functionality of a class or add additional functionality to a class.

  • Functions need to be added to an object dynamically, and these functions can be revoked dynamically.

  • Need to modify or add functions for a batch of sibling classes, of course, is the preferred decoration mode.

structure

Component Abstract: Component is an interface or abstract class that defines our core object, the original object. In the decorator pattern, there must be a basic, core, primitive interface or abstract class that acts as the Component abstraction.

ConcreteComponent Concrete: ConcreteComponent is the core, primitive, and basic implementation of an interface or abstract class that you want to decorate.

Decorator: Usually an abstract class, what does it do? An implementation interface or abstract method does not have an abstract method in it. It must have a private variable in its property pointing to the Component abstract.

ConcreteDecoratorA and ConcreteDecoratorB are two ConcreteDecoratorA classes in which you decorate your core, original, and basic things into something else. The above example is ConcreteDecoratorA and ConcreteDecoratorB, in which you decorate a mediocre report card into a parent-approved report card.

Code sample

/ / @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 "); }}Copy the code

The strategy pattern

concept

Define a set of algorithms, encapsulate each algorithm, and make them interchangeable.

Usage scenarios

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

  • Scenarios where the algorithm needs to switch freely.

  • Scenarios where algorithm rules need to be masked.

  • If the number of policies exceeds four, use the mixed mode

structure

Context encapsulating role: It is also called the Context role. It acts as a link between the preceding and the following to shield the high-level module from direct access to policies and algorithms, and encapsulates possible changes.

Strategy Abstract Policy role: An abstraction of a policy or algorithm family, usually an interface, that defines the methods and attributes that each policy or algorithm must have.

ConcreteStrategy Concrete Policy Role: Implements operations in an abstract policy. This class contains concrete algorithms.

Code sample

Public enum Calculator {ADD("+"){public int exec(int a,int b){return a+b; public enum Calculator {ADD("+"){public int exec(int a,int b){return a+b; SUB("-"){public int exec(int a,int b){return a - b; }}; String value = ""; Private Calculator(String _value){this.value = _value; } public String getValue(){return this.value; } public abstract int exec(int a,int b); }Copy the code

Adapter mode

concept

Transform the interface of one class into another that the client expects, so that two classes that would otherwise not work together because of interface mismatches can work together.

Usage scenarios

When you have an incentive to modify an interface that is already in production, the adapter pattern may be the best pattern for you. For example, when the system is extended, it needs to use an existing or newly created class, but this class does not conform to the interface of the system, what to do? Do not consider using the adapter pattern during the detailed design phase, and use the main scenario for extended applications.

The class adapter

Target Target role: This role defines the interface to which other classes are converted, that is, our desired interface.

Adaptee Source Role: The “who” you want to convert to the target role is the source role, which is an existing, well-functioning class or object wrapped by the Adaptee role into a new, beautiful role.

Adapter Adapter role: The core role of the Adapter pattern. The other two roles are existing roles, but the Adapter role needs to be newly created. Its responsibility is very simple: convert the source role to the target role. Through inheritance or class association.

Object adapter

Instead of using multiple inheritance or inheritance, use direct association, or delegation.

Differences between object adapters and class adapters:

Class adapter is the inheritance between classes, while object adapter is the composite relation of objects, or the association relation of classes, which is the fundamental difference between the two. The scenarios used by object adapters are relatively common in real projects.

Code sample

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

Iterator pattern

concept

It provides a way to access individual elements of a container object without exposing the inner details of the object.

structure

Iterator: An abstract Iterator defines an interface for accessing and iterating elements, and basically has three fixed methods: First () gets the first element, next() accesses the next element, and isDone() has already accessed the bottom (Java is called the hasNext() method).

ConcreteIterator: The ConcreteIterator role implements the iterator interface that iterates through container elements.

Aggregate: The container role is responsible for providing an interface to create concrete iterator roles, which must provide a method like createIterator(), which in Java is generally iterator().

Concrete Aggregate: Concrete containers implement methods defined by the container interface to create objects that hold iterators.

Code sample

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; }}Copy the code

Portfolio model

concept

Objects are grouped into a tree structure to represent a partial-whole hierarchy, allowing consistency in the use of individual objects and composite objects.

Usage scenarios

  • Maintain and display partial-overall relationship scenarios, such as tree menus, file and folder management.

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

  • As long as you have a tree structure, consider using composite patterns.

structure

Component Abstract Roles: Define common methods and properties that participate in composite objects. You can define some default behaviors or properties.

Leaf: A Leaf object that has no further branches under it and is the smallest unit to traverse.

Composite: A branch object that combines branch and leaf nodes to form a tree structure.

Code sample

Public Class Composite extends Component {private ArrayList<Component> componentArrayList = new ArrayList<Component>(); Components / / add a leaf or branch member public void the add Component (Component) {this.com ponentArrayList. Add (Component); } / / delete a member leaves or branches artifacts public void remove Component (Component) {this.com ponentArrayList. Remove (Component); } public ArrayList<Component> getChildren(){return this.componentArrayList; }}Copy the code

Observer model

concept

Define a one-to-many dependency between objects so that whenever an object changes state, all dependent objects are notified and automatically updated.

Usage scenarios

  • Associated behavior scenarios. It is important to note that associative behavior is separable, not “composed” relationships.

  • Multi-level event triggering scenario.

  • Cross-system message exchange scenarios, such as message queue processing mechanisms.

structure

Subject observed: Defines the responsibilities that the observed must fulfill. It must be able to dynamically add and remove observers. It is generally an abstract class or an implementation class that does only what it must do as an observed: manage and inform the observer.

Observer: After receiving a message, the Observer performs an update operation to process the received message.

ConcreteSubject Concreteobserved: Defines the observed’s own business logic and defines which events are notified.

ConcreteObserver: Each observer has its own processing logic after receiving a message.

Code sample

Private Vector<Observer> obsVector = new Vector<Observer>(); Public void addObserver(Observer o){this.obsvector.add (o); } public void delObserver(Observer o){this.obsvector.remove (o); Public void notifyObservers(){for(Observer o: this.obsvector){o.update(); }}}Copy the code

Facade pattern

concept

It is required that communication between the outside and the inside of a subsystem must be carried out through a unified object. Facade mode provides a high-level interface that makes subsystems easier to use.

Usage scenarios

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

  • Subsystems are relatively independent — external access to the subsystem is a black box operation

  • Prevent the spread of risk from low-level personnel

structure

Facade Role: Methods that clients can invoke for this role. This role knows all the functions and responsibilities of the subsystem. Typically, this role delegates all requests from the client to the appropriate subsystem, meaning that this role has no actual business logic and is just a delegate class.

Subsystem Role: Can have one or more subsystems at the same time. Each subsystem is not a single class, but a collection of classes. The subsystem is unaware of the facade. To a subsystem, a facade is just another client.

Code sample

Public class Client {// Delegate subsystem object private A A = new A(); private B b= new B(); private C c= new C(); Public void methodA(){this.a.dosomething (); } public void methodB(){ this.b.doSomething(); } public void methodC(){ this.c.doSomething(); }}Copy the code

Memo mode

concept

Capture the internal state of an object and store the state outside of the object without breaking encapsulation. You can then restore the object to its original saved state.

Usage scenarios

  • Status-related scenarios in which data needs to be saved and restored.

  • Provide a rollback operation.

  • In the duplicate scenario to be monitored.

  • The transaction management of database connections is the memo pattern.

structure

Originator Originator: records internal status at the current time, defines states that belong to the backup scope, and creates and restores memo data.

Memento Role: Stores the internal status of Originator objects and provides the internal status required by Originator objects.

Caretaker role: manages, saves, and provides Caretaker memos.

Code sample

Public class BeanUtils {public static Hashmap <String,Object> backupProp(Object bean){public static Hashmap <String,Object> backupProp(Object bean){ HashMap<String,Object> result = new HashMap<String,Object>(); BeanInfo BeanInfo =Introspector.getBeanInfo(bean.getClass())); / / get the property description PropertyDescriptor [] descriptors. = beanInfo getPropertyDescriptors (); For (PropertyDescriptor des:descriptors){// String fieldName = des.getName(); Getter = des.getreadMethod (); Object fieldValue=getter.invoke(bean,new Object[]{}); if(! fieldName.equalsIgnoreCase("class")){ result.put(fieldName, fieldValue); }}} catch (Exception e) {return result; Public static void restoreProp(Object bean,HashMap<String,Object> propMap){try {// Get the bean BeanInfo BeanInfo = Introspector.getBeanInfo(bean.getClass())); / / get the property description PropertyDescriptor [] descriptors. = beanInfo getPropertyDescriptors (); For (PropertyDescriptor des:descriptors){// String fieldName = des.getName(); If (propmap.containsKey (fieldName)){setMethod = des.getwritemethod (); setter.invoke(bean, new Object[]{propMap.get(fieldName)}); }}} catch (Exception e) {system.out.println ("shit"); e.printStackTrace(); }}}Copy the code

Visitor pattern

concept

Encapsulates operations that operate on elements of a data structure and defines new operations that operate on those elements without changing the data structure.

Usage scenarios

  • An object structure contains many class objects that have different interfaces, and you want to perform operations on these objects that depend on their concrete classes, i.e. the iterator pattern is no longer sufficient.

  • There are many different and unrelated operations to be performed on objects in an object structure, and you want to avoid having those operations “contaminate” the classes of those objects.

structure

Visitor – Abstract Visitor: An abstract class or interface that declares which elements visitors can access. Specifically, the parameters of the visit method define which objects can be accessed.

ConcreteVisitor – ConcreteVisitor: this affects what the visitor should do and what to do after visiting a class.

Element — Abstract Element: An interface or abstract class that declares what kind of visitors it accepts, programmatically defined by parameters in the Accept method.

ConcreteElement — ConcreteElement: implementing the accept method, usually visit.visit (this), basically forms a pattern.

ObjectStruture — Structural objects: Element producers, typically held in multiple containers of different classes and interfaces, such as lists, sets, maps, etc., rarely abstracted in a project.

Code sample

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)); }}Copy the code

The state pattern

concept

Allowing an object to change its behavior when its internal state changes, the object appears to have changed its class.

Usage scenarios

  • The scenario in which behavior changes with state changes is also the fundamental starting point of state mode. For example, in the design of permissions, the same behavior will result in different results even if the state of personnel is different. In this case, state mode should be considered.

  • Alternatives to conditional, branch judgment statements

structure

State — Abstract State role: Interface or abstract class responsible for object State definition and encapsulating environment role to enable State switching.

ConcreteState – ConcreteState Role: Each ConcreteState must fulfill two responsibilities: behavior management for the state and handling of the trending state, which, in layman’s terms, is what to do in the state and how to transition from the state to other states.

Context – Environment role: defines the interface required by the client and is responsible for switching the specific state.

Code sample

Public abstract class State {// Define an environment role that provides subclasses to access protected Context Context; Public void setContext(Context _context){this. Context = _context; } public void handle1(); Public abstract void handle2(); }Copy the code

Interpreter mode

concept

Given a language, define a representation of its grammar and define an interpreter that uses that representation to interpret sentences in the language.

Usage scenarios

  • Recurring problems can be solved using the interpreter pattern

  • A scenario where simple syntax needs to be explained

structure

AbstractExpression — Abstract interpreter: Concrete interpretation tasks are performed by implementation classes, and concrete interpreters are performed by TerminalExpression and non-TerminalExpression respectively.

TerminalExpression — TerminalExpression: Implements interpretive operations associated with elements ina grammar. Usually there is only one TerminalExpression in an interpreter schema, but there are multiple instances corresponding to different terminals. Our example is the VarExpression class. Each terminator in an expression creates a VarExpression object in the stack.

NonterminalExpression — Non-terminal expression: Each rule ina grammar corresponds to a non-terminal expression. In our case, the addition and subtraction rules correspond to the classes AddExpression and SubExpression respectively. Non-terminal expressions increase according to the complexity of the logic, and in principle there is a non-terminal expression for every grammar rule.

Context — Context role: In our example we use HashMap instead.

Code sample

Public class TerminalExpression extends AbstractExpression {@override public void interpret(Context) CTX) {public class NonterminalExpression extends AbstractExpression {public class NonterminalExpression extends AbstractExpression { @override public void interpret(Context CTX) {// Implement an interpretation associated with a non-terminal in a grammar rule}}Copy the code

The flyweight pattern

concept

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

The information of objects is divided into two parts: intrinsic and extrinsic.

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

External state: An external state is a token on which an object can depend. It is a state that changes with the environment and cannot be shared.

Usage scenarios

  • A large number of similar objects exist in the system.

  • Fine-grained objects have a close external state, and the internal state is context-independent, that is, the object has no specific identity.

  • Scenarios where buffer pools are required.

structure

Flyweight – Abstract share role: It is simply an abstract class of a product that defines both the external state of the object and the interface or implementation of the internal state.

ConcreteFlyweight – Concrete Role: A concrete product class that implements an abstract role defined service. The important thing to note in this role is that the internal state processing should be independent of the environment. There should be no operation that changes the internal state while changing the external state, which is never allowed.

UnsharedConcreteFlyweight – do not share the flyweight role: there is no external state or security requirements (such as thread safe) will not be able to use objects of sharing technology, the object does not generally appear in the flyweight factory.

FlyweightFactory: The responsibility is very simple, constructing a pool container and providing methods to get objects from the pool.

Code sample

Public class FlyweightFactory {// Define a pool private static HashMap<String,Flyweight> pool= new HashMap<String,Flyweight>(); Public static Flyweight getFlyweight(String Extrinsic){// Need to return Flyweight Flyweight = null; If (pool. ContainsKey (Extrinsic)){flyweight = pool. Get (Extrinsic); }else{flyweight = new ConcreteFlyweight1(Extrinsic); // Pool. Put (Extrinsic, flyweight); } return flyweight; }}Copy the code

Bridge pattern

concept

Decouple the abstraction from the implementation so that the two can vary independently.

Usage scenarios

  • Scenarios where inheritance is not desired or applicable

  • Scenarios where interfaces or abstract classes are unstable

  • Scenarios with high reusability requirements

structure

Abstraction — Abstract character: Its main responsibility is to define the behavior of the character while keeping a reference to the implemented character, which is generally an abstract class.

Implementor — Implements the role: This is an interface or abstract class that defines the required behavior and properties of the role.

RefinedAbstraction — RefinedAbstraction character: It uses RefinedAbstraction character as a reference.

ConcreteImplementor — ConcreteImplementor: Implements methods and properties defined by an interface or abstract class.

Code sample

Public Abstract class Abstraction {// Define a reference to the implementation role private Implementor IMP; // Constraint subclass must implement the constructor public Abstraction(Implementor _IMP){this.imp = _IMP; } public void request(){this.imp. DoSomething (); Public Implementor getImp(){return imp; }}Copy the code

conclusion

When you’re learning design patterns, don’t make it sound like it’s hard, but it’s all just general summaries. We need to gradually understand its deep principles in our daily study and work, so that we can flexibly apply each design mode.

Design mode is a solution to some of the problems of the scene on the previous summary, design mode is not a formula, there is no need to memorize every mode, more important is to understand its abstract ideas, and how to apply design mode to better solve the problem, what effect can be achieved. ** theory is much, but if we want to master it, it will solve many problems for our actual development.

Of course, I will continue to update you on design principles to further understand design patterns.