1. Template method pattern
Basic introduction
1) Template Method Pattern, also known as template pattern, defines the template of the method executing it in an abstract class. Its subclasses can override the method implementation as needed, but the call will be made in the way defined in the abstract class.
2) In short, the template method pattern defines the skeleton of an algorithm in operation, and delays some steps to subclasses, so that subclasses can redefine some specific steps of an algorithm without changing the structure of an algorithm
3) This type of design pattern belongs to behavioral pattern.
Main solution: some methods are common, but this method is rewritten in each subclass.
Usage scenario: 1. There are methods shared by multiple subclasses with the same logic. 2. Important and complex methods can be considered as template methods.
For example:
1. Create an abstract class whose template method is set to final.
public abstract class Game { abstract void initialize(); abstract void startPlay(); abstract void endPlay(); //Template public final void play(){ //Initialize game initialize(); //Start the game startPlay(); //End the game endPlay(); } }
2. Create an entity class that extends the above class.
public class Cricket extends Game { @Override void endPlay() { System.out.println("Cricket Game Finished!"); } @Override void initialize() { System.out.println("Cricket Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Cricket Game Started. Enjoy the game!"); } }
public class Football extends Game { @Override void endPlay() { System.out.println("Football Game Finished!"); } @Override void initialize() { System.out.println("Football Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Football Game Started. Enjoy the game!"); } }
3. User
public class TemplatePatternDemo { public static void main(String[] args) { Game game = new Cricket(); game.play(); game = new Football(); game.play(); } }
Hook method of template mode
In the parent class of the template method pattern, we can define a method that does nothing by default, and the subclass can override it according to the situation. This method is called "hook".
For example, we want to make pure soybean milk without adding any ingredients. Please use the hook method to transform the template method
//Abstract class representing soybean milk public abstract class SoyaMilk { //Template methods, make, and template methods can be made final without subclass coverage final void make() { select(); if(customerWantCondiments()) { addCondiments(); } soak(); beat(); } //Material selection void select() { System.out.println("Step 1: choose good fresh soybeans "); } //Add different ingredients, abstract methods and subclasses abstract void addCondiments(); //soak void soak() { System.out.println("Third, soybeans and ingredients begin to soak, which takes 3 hours "); } void beat() { System.out.println("Step 4: put the soybeans and ingredients into the soybean milk machine to break them "); } //Hook method to determine whether ingredients need to be added boolean customerWantCondiments() { return true; } }
Source code analysis of application of template method pattern in Spring framework
Class diagram:
2. Command mode
Command Pattern is a data-driven design pattern, which belongs to behavioral pattern. The request is wrapped in the object in the form of a command and passed to the calling object. Call the object to find the appropriate object that can process the command, pass the command to the corresponding object, and the object executes the command.
Intent: encapsulate a request into an object so that you can parameterize the customer with different requests.
Main solution: in software systems, the behavior requester and behavior implementer are usually closely coupled, but in some cases, such as when it is necessary to record, undo or redo, and deal with transactions, this kind of tightly coupled design that cannot resist changes is not suitable.
Usage scenario: you can use the command mode wherever you think it is a command, for example: 1. Every button in the GUI is a command. 2. Simulate CMD.
Key code: define three roles: 1. received real command execution object 2. Command 3. invoker uses the entry of command object
1. Create command interface:
public interface ICommand { void execute(); }
2. Specific command implementation classes
public class CommandA implements ICommand{ private Receiver receiver; public CommandA(Receiver receiver) { this.receiver = receiver; } @Override public void execute() { System.out.println("CommandA implement ....."); receiver.execute(); } } public class CommandB implements ICommand{ private Receiver receiver; public CommandB(Receiver receiver) { this.receiver = receiver; } @Override public void execute() { System.out.println("CommandB execute ..."); receiver.execute(); } }
3. Receiver: the object that executes the command. How to execute the command
public class Receiver { public void execute(){ System.out.println("Receiver Execute command"); } }
4. Invoker: create a command entry and execute the command
public class Invoker { private ICommand CommandA; private ICommand CommandB; public Invoker(ICommand commandA, ICommand commandB) { CommandA = commandA; CommandB = commandB; } //Execute command A public void orderA(){ CommandA.execute(); } //Execute command B public void orderB(){ CommandB.execute(); } }
5. User
public static void main(String[] args) { Receiver receiver = new Receiver(); Invoker invoker = new Invoker(new CommandA(receiver), new CommandB(receiver)); invoker.orderA(); invoker.orderB(); }
The JdbcTemplate of the Spring framework uses the command mode
code analysis
- StatementCallback interface, similar to command interface
- class QueryStatementCallback implements StatementCallback,SqlProvider, an anonymous inner class, implements the command interface and also acts as the command receiver
- The command caller Invoker is JdbcTemplate, in which execute(StatementCallback action) method calls action.. Doinstatement method Different objects implementing statementcallback interface correspond to different doInStatemnt implementation logic
- In addition, the subclasses that implement the StatementCallback command interface include QueryStatementCallback
3. Visitor mode
1) Visitor Pattern encapsulates some operations that act on the elements of a data structure. It can define new operations that act on these elements without changing the data structure.
2) It mainly separates data structure from data operation to solve the problem of data structure and operation coupling
3) The basic working principle of visitor mode is to add an interface to the visited class to receive visitors
4) The main application scenarios of visitor mode are: you need to perform many different operations on objects in an object structure (these operations are not related to each other). At the same time, you need to avoid these operations "polluting" the classes of these objects. You can choose visitor mode
1. Element defines an accept method to receive a visitor object
public interface ComputerPart { void accept(ComputerPartVisitor computerPartVisitor); }
2. ConcreteElement is a concrete element and implements the accept method
public class Computer implements ComputerPart{ ComputerPart[] parts; public Computer() { this.parts = new ComputerPart[]{new Mouse(),new Keyboard(),new Monitor()}; } @Override public void accept(ComputerPartVisitor computerPartVisitor) { for (int i = 0; i < parts.length; i++) { parts[i].accept(computerPartVisitor); } computerPartVisitor.visit(this); } } public class Keyboard implements ComputerPart{ @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } } public class Monitor implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } } public class Mouse implements ComputerPart { @Override public void accept(ComputerPartVisitor computerPartVisitor) { computerPartVisitor.visit(this); } }
3. Visitor is an abstract visitor that declares a visit operation for each class of ConcreteElement in the object structure
public interface ComputerPartVisitor { void visit(Computer computer); void visit(Mouse mouse); void visit(Keyboard keyboard); void visit(Monitor monitor); }
4. ConcreteVisitor: it is a specific access value to implement each operation declared by Visitor, which is a part of each operation implementation
public class ComputerPartDisplayVisitor implements ComputerPartVisitor{ @Override public void visit(Computer computer) { System.out.println("Exhibition computer"); } @Override public void visit(Mouse mouse) { System.out.println("Display mouse"); } @Override public void visit(Keyboard keyboard) { System.out.println("Display keyboard"); } @Override public void visit(Monitor monitor) { System.out.println("Display display"); } }
5. User
public static void main(String[] args) { ComputerPart computer = new Computer(); computer.accept(new ComputerPartDisplayVisitor()); }
4. Iterator mode
This pattern is used to access the elements of the collection object sequentially without knowing the underlying representation of the collection object.
Main solution: traverse the entire integration object in different ways.
When to use: traverse an aggregate object.
How to solve it: leave the responsibility of swimming between elements to the iterator, not the aggregate object.
Key code: define interface: hasNext, next.
Application example: iterator in JAVA.
Usage scenario: 1. Access the content of an aggregate object without exposing its internal representation. 2. You need to provide multiple traversal methods for aggregate objects. 3. Provide a unified interface for traversing different aggregation structures.
1. Iterator interface
public interface Iterator { boolean hasNext(); Object next(); }
2. Returns the Container interface of the iterator
public interface Container { Iterator getIterator(); }
3. The entity class that implements the Container interface will be responsible for implementing the Iterator interface.
public class NameRepository implements Container{ public String[] names={"robert","john","julie","lora"}; @Override public Iterator getIterator() { return new NameIterator(); } private class NameIterator implements Iterator{ int index; @Override public boolean hasNext() { if (index<names.length){ return true; } return false; } @Override public Object next() { if (this.hasNext()){ return names[index++]; } return null; } } }
4. Use
public static void main(String[] args) { NameRepository nameRepository=new NameRepository(); Iterator iterator = nameRepository.getIterator(); while(iterator.hasNext()){ String name = (String)iterator.next(); System.out.println("Name : " + name); } }
5. Observer mode
Application scenario: some businesses need to be maintained and modified continuously. If you constantly modify this method, it may cause business logic errors
It breaks the principle of single responsibility and couples a lot of code with attributes.
It breaks the opening and closing principle (extension without modifying the code). For example, when I create an order, I have to send wechat messages. I must modify the code to expand the function, or I have to use this method when I want to modify the logic of sending text messages.
Optimization: disassemble 2, 3 and 4, package them into a class, and then similarly execute them one by one with a for loop. It's observer mode
example:
public class OrderEvent extends ApplicationEvent { Long id; public OrderEvent(Object source,Long id) { super(source); this.id = id; } } // The logic of sending e-mail is put into a class @Component public class EmailListener implements ApplicationListener<OrderEvent> { @Override public void onApplicationEvent(OrderEvent orderEvent) { System.out.println("send emails: " + orderEvent.id); } } // Put the logic of sending text messages into a class @Component public class SmsListener implements ApplicationListener<OrderEvent> { @Override public void onApplicationEvent(OrderEvent orderEvent) { System.out.println("The logic of sending text messages." + orderEvent.id); } } @Service public class DeviceBusinessPurposeServiceImpl extends ServiceImpl<DeviceBusinessPurposeMapper, DeviceBusinessPurpose> implements DeviceService { @Autowired private ApplicationContext applicationContext; @Override public void createOrder() { // Create order Long id = 1L; System.out.println("Create order"); // Publish order related events (there are many events in Spring, and the event to be published is the event of OrderEvent) // Call the business logic in the class circularly applicationContext.publishEvent(new OrderEvent(applicationContext, id)); } } ps: there Event and Listener ,Direct use Spring Provided. You can also write it yourself