I started studying design patterns from the beginning of this year. Recently, I felt that the input became excessive, so I wrote a summary of the Template Method as a place to output what I learned. I hope it will be helpful to the reader. Also, I would be grateful if you could point out any mistakes or concerns.
--What makes you happy with the Template Method? --Class diagram --DisplayFigure class --Circle class --Square class --Actually move --Try changing the logic
By using the Template Method, you can ** combine common processes into one **, reduce the number of modifications when you want to change the logic later, and improve the maintainability of the code. I think it is difficult to understand from this explanation alone, so I will explain it with an actual program.
There are Circle and Square that inherit from the abstract class DisplayFigure. The Main class uses the methods of the child class via the DisplayFigure class.
DisplayFigure.java
public abstract class DisplayFigure {
public void init() {
System.out.println("-- start!! --");
}
public abstract void printFigure();
public void finish() {
System.out.println("-- finish!! --");
}
public void final display() {
init();
for(int i = 0; i < 5; i ++) {
for(int j = 0; j <= i; j ++) {
printFigure();
}
System.out.println();
}
finish();
}
}
This class implements the process of displaying figures. This class is an abstract class that implements the abstract method printFigure ()
and forces its child classes to implement it. In dispaly ()
, the above three methods are grouped together, and the processing in the child class is standardized. The important thing here is the final
qualifier, and methods with this qualifier cannot be overridden and rewritten in child classes. Isn't it possible to read the intention to use this method as it is?
Circle.java
public class Circle extends DisplayFigure {
private char symbol;
public Circle(char symbol) {
this.symbol = symbol;
}
public void printFigure() {
System.out.print(symbol);
}
}
Next, let's look at the Circle class that inherits the DisplayFigure class. It implements the contents of printFigure ()
defined in the upper class. Since the logic is implemented in the parent class, it is a relatively simple implementation. The figure is displayed using the symbol of the variable symbpl that was initialized at the time of class creation. When initialized with the symbol ●, it becomes as follows.
Execution example
-- start!! --
●
●●
●●●
●●●●
●●●●●
-- finish!! --
Square.java
public class Square extends DisplayFigure {
private char symbol;
public Square(char symbol) {
this.symbol = symbol;
}
public void printFigure() {
System.out.print(symbol);
}
}
This class inherits DisplayFigure.java
as well as Circle.java
. Initializing this class with the symbol ■ yields the following execution results. The Main class that runs this program is explained at the end.
Execution example
-- start!! --
■
■■
■■■
■■■■
■■■■■
-- finish!! --
You can see that Circle
and Square
are doing ** common processing **, only the difference is whether the triangle is drawn with ● or ■.
Let's create a Main class and actually run it.
Main.java
public class Main {
public static void main(String[] args) {
DisplayFigure circle = new Circle('●');
DisplayFigure square = new Square('■');
circle.display();
square.display();
}
}
Execution result
-- start!! --
●
●●
●●●
●●●●
●●●●●
-- finish!! --
-- start!! --
■
■■
■■■
■■■■
■■■■■
-- finish!! --
What you should pay attention to here is that ** the created instance is assigned to a variable of the type of abstract class (upcast) **. Then, instead of calling the methods of the child class directly, the abstract class display ()
of the DisplayFigure
class is called. Thanks to this, if you want to change the logic, you only have to change the display ()
of the DisplayFigure
class.
Finally, let's change the logic. So far, we have displayed triangles, so let's rewrite it to a program that displays rectangles.
Display Figure after change.java
public abstract class DisplayFigure {
public void init() {
System.out.println("-- start!! --");
}
public abstract void printFigure();
public void finish() {
System.out.println("-- finish!! --");
}
/* public final void display() {
init();
for(int i = 0; i < 5; i ++) {
for(int j = 0; j <= i; j ++) {
printFigure();
}
System.out.println();
}
finish();
} */
//Changed to a program that displays rectangles
public final void display() {
init();
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
printFigure();
}
System.out.println();
}
finish();
}
}
When you run ...
Execution result after change
-- start!! --
●●●●●
●●●●●
●●●●●
●●●●●
●●●●●
-- finish!! --
-- start!! --
■■■■■
■■■■■
■■■■■
■■■■■
■■■■■
-- finish!! --
I was able to change the behavior of the two classes, Circle
and Square
, simply by changing the print ()
of the DisplayFigure
class.
Reference book: [Introduction to Design Patterns Learned in the Augmented and Revised Java Language](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8 % 82% E7% 89% 88Java% E8% A8% 80% E8% AA% 9E% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 82% B6 % E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3% E5% 85% A5% E9% 96% 80-% E7% B5% 90% E5% 9F% 8E-% E6% B5% A9 / dp / 4797327030 / ref = sr_1_1? __mk_ja_JP =% E3% 82% AB% E3% 82% BF% E3% 82% AB% E3% 83% 8A & crid = 3V4BASNVFTA6O & keywords =% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3 % 83% B3 & qid = 1564625886 & s = gateway & sprefix =% E3% 81% A7% E3% 81% 96% E3% 81% 84% E3% 82% 93% E3% 81% B1% E3% 81% 9F% 2Caps% 2C301 & sr = 8-1)
Recommended Posts