It seems that one mode per day is too slow and lacks content, so try 3-4 modes per article and make it better in 2 days.

First of all, commonly used design patterns are divided into three categories: creation patterns, behavior patterns and structural patterns. The factory and Builder patterns written in the previous two articles are part of the creation pattern.

Chain of Responsibility model

The chain of responsibility model can be split into responsibility and chain, responsibility is the responsibility to do something, chain can refer to the linked list, there is a next level.

Scenario: Now you are an employee of a company, and you have received an urgent document (the urgency of documents must be different), and you need a higher level of management to process the document.

Normal mode

File types:

public class File {

    private FileClass fileClass;	// The importance level of the file
    private String content;			// The contents of the file

    / / to omit

}

// Enumeration classes represent the importance level of a file
enum FileClass {
    NORMAL,
    IMPORTANT,
    EMERGENCY
}
Copy the code

Employee interface:

public interface IStaff {
    // Get the employee's name
    public String getName(a);
    
    // Get the level of the file to process
    public FileClass getFileClass(a);
    
    // Capture employee needs
    public String getRequest(a);    
}
Copy the code

Staff:

public class Staff implements IStaff {
    private File file;
    private String name;

	// omit the constructor

    @Override
    public String getName(a) {
        return name;
    }

    @Override
    public FileClass getFileClass(a) {
        return file.getFileClass();
    }

    @Override
    public String getRequest(a) {
        return "This document [" + file.getContent() +"】 Needs to be dealt with."; }}Copy the code

Leadership interface:

public interface IHandler {
    // Process files
    public void handle(IStaff staff);
}
Copy the code

The group leader:

public class Leader implements IHandler {
    @Override
    public void handle(IStaff staff) {
        System.out.println(staff.getName() + ":" + staff.getRequest());
        System.out.println("Leader: Deal with it now"); }}Copy the code

Director:

public class Director implements IHandler{
    @Override
    public void handle(IStaff staff) {
        System.out.println(staff.getName() + ":" + staff.getRequest());
        System.out.println("Director: Deal with it now"); }}Copy the code

Director:

public class Supervisor implements IHandler {
    @Override
    public void handle(IStaff staff) {
        System.out.println(staff.getName() + ":" + staff.getRequest());
        System.out.println("Supervisor: Deal with it now"); }}Copy the code

Client:

public class Client {
    public static void main(String[] args) {
        File file = new File(FileClass.IMPORTANT, "Planning scheme");
        IStaff staff = new Staff(file, "imperfect");
        
        if(file.getFileClass().equals(FileClass.NORMAL)) {
            new Leader().handle(staff);
        } else if(file.getFileClass().equals(FileClass.IMPORTANT)) {
            new Director().handle(staff);
        } else if(file.getFileClass().equals(FileClass.EMERGENCY)) {
            new Supervisor().handle(staff);
        } else {
            System.out.println("Insufficient authority"); }}}Copy the code

Take a look, and look carefully, this bunch of if else’s are exposed directly in the Client class, and it’s in the Client class that the judgment is made that different levels are handled by different leaders.

The common metaphor is that after the employee gets the document, he calls his team leader, director and supervisor to him and says, “This document is very important. Who can handle it for you?” It is possible to complete characters, but is it realistic?

One way to approach reality is for employees to get the file and first give it to their immediate leader, the lowest level in the hierarchy (handler). Then the group leader will see if he is responsible to deal with the documents, if not, then to the next layer to deal with, this is the responsibility chain mode.

Chain of Responsibility model

The file and employee classes remain the same, with handler being the main change.

Abstract Leadership class:

public abstract class AbstractHandler {
    private FileClass fileClass;
    private AbstractHandler nextHandler;
    private String name;

    // The responsibilities are specified when the class is constructed
    // Just like you know what your responsibilities are when you enter the company
    public AbstractHandler(FileClass fileClass, String name) {
        this.fileClass = fileClass;
        this.name = name;
    }

    // Get the name of the leader
    public String getName(a) {
        return name;
    }

    // No responsibility, pass to the next level
    public void setNextHandler(AbstractHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    // Everyone responds differently, so abstract it out
    public abstract void respond(IStaff staff);

    // Process information
    public void handle(IStaff staff) {
        if(fileClass.equals(staff.getFileClass())) {
            respond(staff);
        } else {
            if(nextHandler ! =null) {
                nextHandler.respond(staff);
            } else {
                System.out.println("Maximum clearance!!"); }}}}Copy the code

The group leader:

public class Leader extends AbstractHandler {

    public Leader(String name) {
        super(FileClass.NORMAL, name);
    }

    @Override
    public void respond(IStaff staff) {
        System.out.println(staff.getName() + ":" + staff.getRequest());
        System.out.println(getName() + "Leader: Responded."); }}Copy the code

Director:

public class Director extends AbstractHandler{

    public Director(String name) {
        super(FileClass.IMPORTANT, name);
    }

    @Override
    public void respond(IStaff staff) {
        System.out.println(staff.getName() + ":" + staff.getRequest());
        System.out.println(getName() + "Director: Responded."); }}Copy the code

Director:

public class Supervisor extends AbstractHandler {

    public Supervisor(String name) {
        super(FileClass.EMERGENCY, name);
    }

    @Override
    public void respond(IStaff staff) {
        System.out.println(staff.getName() + ":" + staff.getRequest());
        System.out.println(getName() + "Supervisor: Responded."); }}Copy the code

Client:

public class Client {
    public static void main(String[] args) {
        File file = new File(FileClass.IMPORTANT, "Marketing plan");
        IStaff staff = new Staff(file, "imperfect");

        // Create leadership
        AbstractHandler leader = new Leader("leaderWu");
        AbstractHandler director = new Director("directorWu");
        AbstractHandler supervisor = new Supervisor("supervisorWu");

        // Set the hierarchy, similar to a linked list
        leader.setNextHandler(director);
        director.setNextHandler(supervisor);

        // Let's give it to our direct managerleader.handle(staff); }}Copy the code

The advantages and disadvantages

  • ** Advantages: ** Processing and requests are separated, and employees do not know who is handling the final document
  • ** Disadvantages: ** disadvantages are also obvious, if the chain of responsibilities is long, and the processor happens to be at the end, do not need to go through the chain of responsibilities. This performance is relatively low, in actual use, generally fold this maximum chain length to ensure performance.

UML class diagrams

Command mode

Command mode, in a word, is to give you an order, you must obey and execute, a bit like the army “obey orders is the bountiful duty of soldiers”.

I don’t know if I have ever participated in mathematical modeling in university. Anyway, I have never participated in mathematical modeling, but I have learned about the general composition. There are generally students who are mainly responsible for searching, students who write codes, students who write papers and teachers in a team

Normal mode

Abstract Member class (Receiver) :

public abstract class NTeammate {

    public abstract void changeRequire(a);

    public abstract void modify(a);

    public abstract void work(a);

}
Copy the code

Searcher:

public class NSearcher extends NTeammate {
    @Override
    public void changeRequire(a) {
        System.out.println("Searcher learns that demand has changed.");
    }

    @Override
    public void modify(a) {}@Override
    public void work(a) {
        System.out.println("Searcher starts searching for relevant information."); }}Copy the code

Writer:

public class NWriter extends NTeammate {
    @Override
    public void changeRequire(a) {
        System.out.println("Writer understands the need to change");
    }

    @Override
    public void modify(a) {
        System.out.println("Writer revises the paper");
    }

    @Override
    public void work(a) {
        System.out.println("Writer begins to write a paper"); }}Copy the code

Coder:

public class NCoder extends NTeammate {
    @Override
    public void changeRequire(a) {
        System.out.println("Coder understands the requirements are changing.");
    }

    @Override
    public void modify(a) {
        System.out.println("Coder modify code");
    }

    @Override
    public void work(a) {
        System.out.println("Coder start code"); }}Copy the code

Teacher:

public class NTeacher {
    public static void main(String[] args) {
        NTeammate writer = new NWriter();
        // I need to change my articlewriter.modify(); writer.work(); }}Copy the code

At the beginning, the Teacher saw that the text was not concise enough, so he called writer and asked him to modify it, so the Teacher class above was created. This is actually good, because the article, revise and polish.

One day later, the teacher took a closer look and found a bug in the algorithm of the code. This bug caused not only the coder to modify the code, but also the writer to modify the corresponding article.

The Teacher should contact not only writer, but also coder. Then how should the Teacher class be modified?

public class NTeacher {
    public static void main(String[] args) {
        NTeammate writer = new NWriter();
        NTeammate coder = new NCoder();
        // Need to fix bugs and articleswriter.modify(); writer.work(); coder.modify(); coder.work(); }}Copy the code

As you can see, there is just one more requirement, and the code has changed a lot from before, which we don’t want to see. Some of you might think of using the mediator pattern, but the mediator pattern is to reduce the coupling between classes, and in this case the searcher, writer, and coder are not coupled, they are all doing their job.

Command mode

It would be nice if there were an Invoker in the squad, which can communicate with the teacher (client). Not only that, but the teacher’s instructions must be of String type when implemented. We can encapsulate the instructions as a class (command), and the captain only needs to issue commands, which instruct the players (receiver) what to do. This is the command mode, the team members must do what they are told to do.

Abstract players and concrete players are the same as above, so I won’t repeat them here.

Abstract command class:

public abstract class AbstractCommand {
    protected Coder coder = new Coder();
    protected Searcher searcher = new Searcher();
    protected Writer writer = new Writer();
    
    // There must be a way to execute, a command
    public abstract void execute(a);
}
Copy the code

Specific Command classes:

All commands can be encapsulated

Changing requirements:

public class ChangeInfoCommand extends AbstractCommand {
    @Override
    public void execute(a) { searcher.changeRequire(); writer.changeRequire(); coder.changeRequire(); }}Copy the code

Modify the article:

public class ModifyArticleCommand extends AbstractCommand {
    @Override
    public void execute(a) { writer.modify(); writer.work(); }}Copy the code

Modify code:

public class ModifyCodeCommand extends AbstractCommand {
    @Override
    public void execute(a) { coder.modify(); coder.work(); writer.modify(); writer.work(); }}Copy the code

Captain class (Invoke) :

public class Captain {
    // Create a connection with the command
    AbstractCommand abstractCommand;

    public Captain(AbstractCommand abstractCommand) {
        this.abstractCommand = abstractCommand;
    }

    public void invoke(a) {
        // Issue an order for the team member to do the corresponding actionabstractCommand.execute(); }}Copy the code

Teacher (Client) :

public class Teacher {
    public static void main(String[] args) {
        AbstractCommand command = new ModifyCodeCommand();
        Captain captain = newCaptain(command); captain.invoke(); }}Copy the code

If the teacher feels bad again, how to do this? There is no need to practice with the members, just put forward another suggestion. The captain does not practice with the members, just issue orders, and the orders instruct the members to do it. Modification is as simple as that, a line of code.

public class Teacher {
    public static void main(String[] args) {
        //AbstractCommand command = new ModifyCodeCommand();
        AbstractCommand command = new ModifyArticleCommand();
        Captain captain = newCaptain(command); captain.invoke(); }}Copy the code

extension

What if, alas, code changes not only require bug fixes and article fixes, but also require searchers to gather information?

public class ModifyCodeCommand extends AbstractCommand {
    @Override
    public void execute(a) {
        searcher.work();	// Just add it in the specific command, the client is completely unaware of itcoder.modify(); coder.work(); writer.modify(); writer.work(); }}Copy the code

Another case is that after some modifications, the teacher finds that the previous version is better, which requires each member to have a callback function to undo the action and return to the previous state, that is, to find the saved file of the previous version. Just add a callback function to the abstract Receiver class:

public abstract class NTeammate {

    public abstract void changeRequire(a);

    public abstract void modify(a);

    public abstract void work(a);
    
    // Specific teammates are implementing callback methods in their own way
    public abstract void rollback(a);

}
Copy the code

Then you add a recall command

public class callBackCommand extends AbstractCommand {
    @Override
    public void execute(a) {
        // Of course, who needs to withdraw can be changedsearcher.rollback(); writer.rollback(); coder.rollback(); }}Copy the code

UML class diagrams

Interpreter mode

This design pattern is quite unpopular in both work and study. The interpreter pattern consists of the following classes

  • Context: The Context encapsulates global information about the interpreter. All specific interpreters need to access the Context.
  • AbstractExpression: An abstract class or interface that declares interpretive methods to perform, implemented by all concrete interpreters
  • TerminalExpression: An interpreter class that implements operations related to the terminator of a grammar. A terminator expression must be implemented and instantiated because it represents the end of the expression.
  • NonTerminalExpreesion: This is a class that implements the different rules or symbols of the syntax. You should create a class for each syntax.

This thing is difficult to explain, there is no good popular explanation, so just look at the example.

AbstractExpression

public interface Expression {
    public float interpret(a);
}
Copy the code

TerminalExpression

public class Number implements Expression{
    private final float number;

    public Number(float number) {
        this.number = number;
    }

    @Override
    public float interpret(a) {
        returnnumber; }}Copy the code

Remember when we talked about streams, TerminalExpression is like a terminaloperation, and NonTerminalExpression is like an intermediate operation

NonTerminalExpression

public class Plus implements Expression{
    Expression left;
    Expression right;

    public Plus(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public float interpret(a) {
        returnleft.interpret() + right.interpret(); }}Copy the code

Note that there is a separate class for each syntax

public class Minus implements Expression {
    Expression left;
    Expression right;

    public Minus(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public float interpret(a) {
        returnleft.interpret() - right.interpret(); }}Copy the code

Context

public class Evaluator {

    public static void main(String[] args) {
        Evaluator evaluator = new Evaluator();
        System.out.println(evaluator.evaluate("3 4 +"));
        System.out.println(evaluator.evaluate("3-4"));
        System.out.println(evaluator.evaluate("4, 3-2 +"));
    }


    public float evaluate(String expression) {
        Stack<Expression> stack = new Stack<>();
        float result = 0;
        for (String token : expression.split("")) {
            Expression exp = null;
            if (isOperator(token)) {
                if (token.equals("+")) {
                    exp = stack.push(new Plus(stack.pop(), stack.pop()));
                } else if (token.equals("-")) {
                    exp = stack.push(new Minus(stack.pop(), stack.pop()));
                }

                if (null! = exp) { result = exp.interpret(); stack.push(newNumber(result)); }}if (isNumber(token)) {
                stack.push(newNumber(Float.parseFloat(token))); }}return result;
    }

    private boolean isNumber(String token) {
        try {
            Float.parseFloat(token);
            return true;
        } catch (NumberFormatException e) {
            return false; }}private boolean isOperator(String token) {
        return token.equals("+") || token.equals("-"); }}Copy the code

UML class diagrams