First, early review
The previous “Java design patterns of the factory method pattern and abstract factory pattern, this paper introduces the three factory pattern, factory method pattern, factory method pattern, simple abstract factory pattern, according to actual scene is introduced in detail the definition of the three modes, practice, finally summarizes the difference between the three ways, and the application of the various models. In this post we will look at the template method pattern and the Builder pattern.
Definition and practice of template method pattern and builder pattern
2.1 Definition and practice of template method pattern
Definition: Define the skeleton of an algorithm in an operation.deferring some steps to subclasses.Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.
Define an algorithm framework in an operation that delays some steps in a subclass. Allows subclasses to redefine specific steps of an algorithm without changing its structure.
In fact, according to the above definition, we can quickly think, the definition of this pattern is not inheritance. Yes, that’s right, the simplest implementation of the template method pattern is inheritance. Let’s start by implementing a template method pattern in code. I believe you have eaten instant noodles bar, let’s use the template method mode to make a noodles.
Public abstract class AbstractTemplate {public abstract void boilWater(); Public void cookNoodles(); Public void putCondiment(); /** Create a template for cooking noodles, boil water first, then add noodles, then add seasoning */ public voidfinish(){
boilWater();
cookNoodles();
putCondiment();
System.out.println("Finished, ready to eat!"); }} public class InstantNoodlesTemplate extends AbstractTemplate{@override public voidboilWater() {
System.out.println("Boil the water!);
}
@Override
public void cookNoodles() {
System.out.println("In instant noodles!");
}
@Override
public void putCondiment() {
System.out.println("Ready for dressing!"); Public class Client {public static void main(String[] args) {AbstractTemplate template=new InstantNoodlesTemplate(); template.finish(); }}Copy the code
The finish() method above defines an algorithm framework that defines the steps to boil the noodles, then add the noodles, and finally add the seasoning. Then each subclass realizes the concrete implementation of how to boil water, what noodles to put in, what spices to put in. This is the template method pattern, implemented through inheritance alone. As simple as that, let’s look at another pattern that is familiar to the template method pattern, the Builder pattern.
2.21 Definition and practice of the Builder pattern
Definition: Separate the construction of a complex object from its representation so that the same construction process can create different representations.
Separating the construction of a complex object from its representation allows the same construction process to create different representations.
The separation of construction and representation of complex objects is used in the cooking scene above. That is to say, the cooking algorithm and definition are separated, that is to say, each specific type of noodles decides how to cook noodles, how to put spices and other specific algorithm steps. Let’s use code to achieve:
Public abstract class AbstractNoodlesMode {private List<String> stepOrders = new ArrayList<>(); Public void boilWater(); Public void cookNoodles(); Public void putCondiment(); /** * public voiddoOther(); /** * Final public void */finish() {
for (String stepOrder : this.stepOrders) {
switch (stepOrder) {
case "boilWater":
boilWater();
break;
case "cookNoodles":
cookNoodles();
break;
case "putCondiment":
putCondiment();
break;
case "doOther":
doOther();
break;
default:
System.out.println("Unrecognized cooking instructions.");
break;
}
}
}
final public void setStepOrders(List<String> stepOrders) { this.stepOrders = stepOrders; }} /** Instant noodles implementation class, since only need to boil water, cook noodles, put seasoning on the line, */ public class InstantNoodles extends AbstractNoodlesMode {@override public voidboilWater() {
System.out.println("Boil water");
}
@Override
public void cookNoodles() {
System.out.println("Put in the instant noodles");
}
@Override
public void putCondiment() {
System.out.println("Add the seasoning.");
}
@Override
public void doOtherPublic class Spaghetti extends AbstractNoodlesMode {@override public voidboilWater() {
System.out.println("Boil water");
}
@Override
public void cookNoodles() {
System.out.println("Put in the pasta.");
}
@Override
public void putCondiment() {
System.out.println("Put in the ketchup.");
}
@Override
public void doOther() {
System.out.println("Add ham, breakfast meat."); Public AbstractBuilder cookNoodles(); public AbstractBuilder cookNoodles(); Public abstract AbstractNoodlesMode build(); } public class abstractNoodlesBuilder extends AbstractBuilder {private AbstractNoodlesMode noodles=new InstantNoodles(); @Override public AbstractBuildercookNoodles() { List<String> steps=new ArrayList<>(); / / kettle steps. Add ("boilWater"); // Add steps. Add ("cookNoodles"); // Add steps. Add ("putCondiment");
this.noodles.setStepOrders(steps);
return this;
}
@Override
public AbstractNoodlesMode build() {
returnthis.noodles; }} public class SpaghettiBuilder extends AbstractBuilder {private AbstractNoodlesMode noodle = new Spaghetti(); @Override public AbstractBuildercookNoodles() { List<String> steps = new ArrayList<>(); / / kettle steps. Add ("boilWater"); // Add steps. Add ("cookNoodles"); // Add steps. Add ("putCondiment"); // Add ham, add breakfast meat steps. Add ("doOther");
this.noodle.setStepOrders(steps);
return this;
}
@Override
public AbstractNoodlesMode build() {
returnthis.noodle; Public class Client {public static void main(String[] args) {AbstractBuilder instantNoodleBuilder = new InstantNoodlesBuilder(); AbstractBuilder spaghettiBuilder = new SpaghettiBuilder(); AbstractNoodlesMode instantNoodle = instantNoodleBuilder.cookNoodles().build(); instantNoodle.finish(); System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --"); AbstractNoodlesMode spaghe = spaghettiBuilder.cookNoodles().build(); spaghe.finish(); }}Copy the code
Let’s run the result as follows:
The above code is organized into a class diagram as follows:
I have omitted the noodle implementation class from the above class diagram, but this does not affect the overall understanding of the builder pattern. Some of you might ask, well, the Builder pattern is a little more complicated than the template method pattern, but it feels very similar, a little confused. Yeah, yeah, they do know each other. But one thing we need to remember is a good way to tell them apart.
- The template method pattern already defines the builder’s algorithm, which is the process, what goes first and what goes later.
- Instead of defining the builder’s procedures, the Builder pattern assigns subclasses to implement the builder’s algorithm, which is the procedure.
With this in mind, we can distinguish the template method pattern from the builder pattern and know when to use the template method pattern and when to use the builder pattern.
Application scenarios of template method pattern and builder pattern
3.1 Application scenarios of the Template Method mode
1. Multiple subclasses have public methods with basically the same logic.
2. Complex algorithm with important core, and need a lot of reuse, the algorithm can be implemented by template method pattern.
3. During code reconstruction and upgrade, the template method mode is very common. In order to ensure downward compatibility, the template method mode is generally adopted.
3.2 Usage scenarios of the Builder pattern
1. The Same method, different execution sequence, produce different event results, can adopt the Builder mode
2. Multiple parts or components can be assembled into an object, but produce different results.
Advantages and disadvantages of template method mode and builder mode
4.1 Template method mode
Advantages:
- Good scalability, as long as the subclass to achieve the specified algorithm, do not need to pay attention to the subsequent combination of algorithms
- Good maintainability.
- In line with the principle of dependency inversion
Disadvantages:
- The downside of personal understanding may be the encapsulation of the core composition method, but this is the nature of the template approach, let’s just say a downside.
4.2 Builder mode
Advantages:
- It is as extensible and maintainable as the template method pattern
- Flexibility, because even the most core combination algorithm is handed over to the subclass implementation, so more flexibility.
Disadvantages:
- Because the combination algorithm is liberalized, the constraint is reduced. Therefore, it may cause the subclass to call the wrong algorithm, bringing potential risks to the system.
Five, the summary
The template method pattern and the Builder pattern are both creative patterns. The code of the two patterns is very similar, and it is easy to get confused, so we can know when to use the template method pattern and when to use the builder pattern by remembering their core differences. Again, the main difference is that the template method pattern defines the core algorithm, which is the assembly process, while the Builder pattern does not define the order in which to build or how many parts to build, leaving the final core process and the implementation of the parts entirely up to the subclasses.
Careful readers in detail in the sure and found I build model appeared instantNoodleBuilder. CookNoodles (). The build () A.B.C code, before we talked in our design pattern opening of Demeter, Demeter’s rule, for example, does not require A.B.C to be dependent on a non-friend class. In fact, it does not require a.gettb.getc to be dependent on a non-friend class. So there’s nothing wrong with Demeter’s law.
Six, reference
Zen of Design Patterns
7. Recommended reading
Java Design Patterns: Factory Method Patterns and Abstract Factory Patterns
“Java Design Pattern Singletons”
The Beginning of JAVA Design Patterns
Introduction to Java Collections: ArrayList
HashMap takes you into Java Collections
Java Lock ReentrantLock (part 1)
Java Lock ReentrantLock (part 2)
Java Lock ReentrantReadWriteLock