Ofo recently announced its arrival in Paris, France, officially entering the 20th country in the world where bike-sharing has changed the way we travel. Take myself as an example. Every time I get off the subway after work, I lock a shared bike at the speed of light and occupy it at the speed of 100 meters before others.

And everyone is repeating the same action, take out the mobile phone unlock, bike, lock, settlement, wow ~ this is what a spectacular scene, and even don’t unlock the bike ride away directly, the lock is broken.

Why use the template method pattern

Now shared bikes are divided by the way of unlocking, generally there are two kinds of scanning code unlocking and password unlocking, to see the realization of the use process of shared bikes.

Normal thinking logic is to abstract a superclass, and subclasses inherit and implement superclass methods. OK, look at the abstract class code:

Public abstract class AbstractClass {public abstract void unlock(); Public void ride(); Public abstract void lock(); Public void pay(); Public void use(); }Copy the code

Abstract classes define several basic processes for us to use shared bikes. Now there are two different ways of unlocking bikes, which inherit abstract classes, with the following codes:

Public class ScanBicycle extends AbstractClass {@override public void unlock() {system.out.println (" scan "); } @override public void ride() {system.out.println (); } @override public void lock() {system.out.println (" lock "); } @override public void pay() {system.out.println (); } @Override public void use() { unlock(); ride(); lock(); pay(); }}Copy the code

The above is to unlock the bike by scanning the code, then look at the password unlock bike, the code is as follows:

Public class CodeBicycle extends AbstractClass {@override public void unlock() {system.out.println (); } @override public void ride() {system.out.println (); } @override public void lock() {system.out.println (" lock "); } @override public void pay() {system.out.println (); } @Override public void use() { unlock(); ride(); lock(); pay(); }}Copy the code

Now that both methods are defined, look at the client call:

public class Client { public static void main(String[] args) { ScanBicycle scanBicycle = new ScanBicycle(); scanBicycle.use(); System.out.println("========================"); CodeBicycle codeBicycle = new CodeBicycle(); codeBicycle.use(); }}Copy the code

The results are as follows:

Scan code lock

It’s a cool ride

locked

settlement

= = = = = = = = = = = = = = = = = = = = = = = =

Scan code lock

It’s a cool ride

locked

settlement

I believe we have seen the problem of code, use method implementation is the same, that is, code duplication, this is the disease must be cured, the prescription is the template mode pattern.

Template method pattern

define

The template method pattern defines abstract classes and declares some abstract basic methods for subclasses to implement different logic, while defining concrete methods in abstract classes to encapsulate abstract basic methods.

UML

There are two roles involved in the template method pattern:

– Abstract template role: Defines a set of base methods for subclasses to implement, and defines and implements template methods that combine base methods.

– Concrete template roles: A basic method to implement abstract template role definitions

The template method pattern also refers to the following method concepts:

Basic method

  • Abstract method: modified by abstract template role declaration and implemented by concrete template role.

  • Hook methods: declared and implemented by abstract template roles that can be implemented and extended by concrete template roles.

  • Concrete method: declared and implemented by abstract template roles, and not implemented by subclasses.

Template method

Abstract template roles declared and implemented, responsible for scheduling basic methods, usually final, do not allow concrete template roles to override. The template approach is also generally a concrete approach.

Patterns of actual combat

Refactor the above code using the template mode pattern to look at the abstract template role as follows:

public abstract class AbstractClass { protected boolean isNeedUnlock = true; */ protected abstract void unlock(); /** * basic method, subclasses need to implement */ protected abstract void ride(); /** * hook method, * * @param isNeedUnlock */ protected void isNeedUnlock(Boolean isNeedUnlock) {this.isNeedUnlock = isNeedUnlock; } /** * public final void use() {if (isNeedUnlock) {unlock(); } else {System. Out. Println (" = = = = = = = = the lock is broken, don't need to unlock the = = = = = = = = "); } ride(); }}Copy the code

The abstract template role defines two basic methods that use bikes, unlock and ride, and a hook method that controls the logical order of template methods. The core is the use template method and the final modifier, which completes the scheduling of basic methods. Note that the basic methods are scheduled sequentially in the template method. Also, the base methods are protected, because they are called in public-decorated template methods and can be implemented by subclasses without being exposed to other class calls.

Now look at the implementation of two specific template roles:

Public class ScanBicycle extends AbstractClass {@override protected void unlock() { System. The out. Println (" = = = = = = = = "+" sweep code lock "+" = = = = = = = = "); } @override protected void ride() {system.out.println (getClass().getSimplename () + ""); } protected void isNeedUnlock(boolean isNeedUnlock) { this.isNeedUnlock = isNeedUnlock; Public class CodeBicycle extends AbstractClass {@override protected void unlock() { System. The out. Println (" = = = = = = = = "+" password lock "+" = = = = = = = = "); } @override protected void ride() {system.out.println (getClass().getSimplename () + ""); } protected void isNeedUnlock(boolean isNeedUnlock) { this.isNeedUnlock = isNeedUnlock; }}Copy the code

As you can see, neither concrete class needs to implement the use method and is now responsible for implementing the logic of the basic method, which is much clearer than the previous implementation. Let’s see how users use it:

public class Client { public static void main(String[] args) { ScanBicycle scanBicycle = new ScanBicycle(); scanBicycle.use(); CodeBicycle codeBicycle = new CodeBicycle(); codeBicycle.use(); }}Copy the code

The running results are as follows:

======== Scan and unlock ========

ScanBicycle is cool to ride

======== Password unlock ========

The CodeBicycle is cool to ride

When I ran to the shared bike at the speed of 100 meters sprint, I found that the lock of the bike was broken, that is, there is no need to open the lock, free of charge, riding home to collect no problem. Call the hook method isNeedUnlock in your code.

public class Client { public static void main(String[] args) { ScanBicycle scanBicycle = new ScanBicycle(); scanBicycle.isNeedUnlock(false); scanBicycle.use(); CodeBicycle codeBicycle = new CodeBicycle(); codeBicycle.isNeedUnlock(true); codeBicycle.use(); }}Copy the code

The running results are as follows:

======== lock is broken, do not unlock ========

ScanBicycle is cool to ride

======== Password unlock ========

The CodeBicycle is cool to ride

As mentioned above, the template method schedules the base method sequentially, which means that the logic in the template method is immutable. Subclasses only implement the base method that can be implemented, but do not change the top-level logic in the template method. The hook method only controls the logic in the template method. It affects the result of the template method and does not change the original logic.

Advantages and disadvantages of the template method pattern

advantages

1) Good encapsulation. Encapsulate public immutable methods in parent classes, and subclasses are responsible for implementing concrete logic.

2) Good expansibility: the added functions are extended by the basic method of subclasses, in line with the single responsibility principle and the open and closed principle.

3) Reuse code.

disadvantages

1) Since code reuse is realized through inheritance to change the algorithm, the flexibility will be reduced.

2) The execution of the subclass affects the result of the parent class, increasing the difficulty of code reading.

conclusion

The template method pattern looks simple, but the whole pattern addresses the core of object-oriented design, such as inheritance encapsulation, inheritance-based code reuse, method implementation, and so on. There are also related to the use of some key words, but also our Java programming needs to master the basis. In general, template method patterns are good to learn from. The next article is the intermediary mode, your praise and attention is my motivation, goodbye!

Design pattern making Java source code download: https://github.com/jetLee92/DesignPattern