Design pattern review - template pattern (C + +)

1 Preface

  Last article This paper summarizes the "appropriate policy mode", describes the meaning, characteristics, advantages and disadvantages, applicable scenarios and implementation process steps of the policy mode, and implements a specific example in C + + language. This paper describes another common design pattern, template pattern, which is similar to policy pattern.


Related articles:

Design pattern review - prototype pattern
Design pattern review - observer pattern
Design pattern review - template pattern
Design pattern review - strategy pattern
Design pattern review - adapter pattern
Review of design pattern - builder pattern
Design mode review - plant mode
Design pattern review - single case pattern
Review of design patterns -- concepts and basic principles of design patterns


2 what is template mode

   Template Pattern refers to defining an abstract (algorithm) template structure parent class, and the specific implementation method is implemented by the child class. Template Pattern is a widely used design pattern in behavioral design pattern.


2.1 template mode composition

   the template pattern consists of three elements: Abstract Class, Concrete Class and Client i.


  • Abstract Class declares a public abstract template parent class. The invariant algorithm is implemented by the parent class, and the difference part is implemented by the child class
  • Concrete Class inherits the Abstract Class and implements the abstract interface and difference part
  • Client: the client realizes different functions by switching different subclasses. Strictly speaking, the client does not belong to the template mode

2.2 template pattern UML diagram

  according to the constituent elements of the template pattern and the relationship between them, draw the UML diagram of the template pattern as follows.

Template pattern UML diagram


2.3 function of formwork mode

   subclasses can redefine the content in a template or some specific steps without changing the structure of a template.


3 advantages and disadvantages of template mode

advantage:

  • Improve code reusability

    The template pattern abstracts the common part of the class code and puts it in the parent class. The child class only needs to implement the difference part to reduce the repeated code of the child class.

  • Easy to expand

    When new functions are added, they are expanded through subclass implementation without changing the original code and code framework, which conforms to the "opening and closing principle".

  • Good flexibility

    All subclasses implement the same set of algorithm model. Where the template is used, different subclasses can achieve different functions by switching, which is in line with the "Richter replacement principle".

  • Good maintainability

    The template pattern behavior is controlled by the parent class and implemented by the child class.


Insufficient:

  • Reduce code readability

    The template method is different from the conventional programming habit. The result of subclass execution affects the result of parent class, which will increase the difficulty of code reading and make it difficult to understand code logic.

Conventional programming habits are generally abstract classes, which are responsible for declaring the most abstract and general thing attributes and methods, and implementation classes are responsible for completing specific transaction attributes and methods, which is in line with the reading thinking and habits of programmers.

  • High coupling

    A subclass cannot affect the public module code of the parent class.

  • Increase system complexity

    New functions need a new subclass to implement, which increases the number of subclasses and increases the complexity of system implementation.


4 where to use template mode

   the advantages of template mode determine the applicable scenarios, while its disadvantages are the inapplicable scenarios. Template mode applicable scenarios:


  • Multiple subclasses have the same methods, logic, algorithms and other basic scenarios, and the common parts can be abstracted

  • Complex algorithm decomposition; the invariant part or core algorithm is designed as a template method, and the relevant detailed functions and variable behaviors are realized by subclasses

  • You need to control the subclass extension scenario; the template mode calls subclass methods at specific points, so that extension is only allowed on these subclasses.

  • Reconstruct the historical legacy code; reconstruct the code by using the template method, abstract the common code into the parent class, and then restrict its behavior through the constructor.


Specific examples:

  • Sorting algorithm: the abstract class defines the sorting interface, and the subclass implements the sorting of specific data types (int, flaot, double, char)

5 template mode implementation

Instance function:

   implement a sorting algorithm, which can sort various types of data such as integer, floating point and character, and select the sorting type.


Instance decomposition:

   the sorting algorithm is divided into several steps, and the common and unchanged ones are implemented by the template method.

[1] Common

  • Algorithm implementation framework

[2] Methods that may change

  • Sort data type
  • sort order
  • Other expansion

General steps:

  • Abstract parent class Sort declares and implements sorting algorithm. This part is common and will not be changed
  • The subclasses IntSort and FlotaSort realize the sorting of integer data and single precision floating-point data respectively
  • Subclasses can also determine the sort method (ascending / descending) without affecting the parent class
  • User client calls subclass instance to select a sort algorithm

Implementation process:

  • The first step is to declare the abstract template class Sort
/* sort.h */
#ifndef _SORT_H_
#define _SORT_H_

#include <stdbool.h>

class Sort
{
public:
	virtual ~Sort();
	virtual void Swap(int)=0;	/* Interactive data */
	virtual bool Judge(int)=0;  /* Data judgment method (sorting method)*/
	void SortRun();				/* Sorting algorithm framework */
protected:
	Sort();
    int m_Size;
};
#endif

  • The second step is to implement the abstract class Sort method
/* sort.cpp */
#include "sort.h"

Sort::Sort()
{
	m_Size = 0;
}

Sort::~Sort()
{
}

void Sort::SortRun()
{
	int i = 0,j = 0;

	for (j=0; j<m_Size-1; j++)
	{
		for (i=0; i<m_Size-1-j; i++)
		{
			if (Judge(i))
			{
				Swap(i);
			}
		}
	}
}
  • Step 3: declare the integer data sorting subclass InstSort to inherit the abstract parent class
/* int_sort.h */
#ifndef _INT_SORT_H_
#define _INT_SORT_H_

#include <stdbool.h>
#include "sort.h"

class IntSort:public Sort
{
public:
	IntSort();
	virtual ~IntSort();

	void Swap(int);		/* Rewrite int data interaction method */
	bool Judge(int);	/* Judgment method of rewriting int data */
	void SortData(int*, int);
private:
	int *m_pArray;
};
#endif
  • Step 4: implement the InstSort method of integer data sorting subclass to realize the sorting data type and sorting method
/* int_sort.cpp */

#include <iostream>
#include "int_sort.h"

using namespace std;

IntSort::IntSort()
{
}

IntSort::~IntSort()
{
}

void IntSort::Swap(int index)
{
	int temp;
	
	temp = m_pArray[index];
    m_pArray[index] = m_pArray[index+1];
    m_pArray[index+1] = temp;
}

bool IntSort::Judge(int index)
{
	return m_pArray[index] > m_pArray[index+1];	/* Sort from small to large */
}

void IntSort::SortData(int *array, int size)
{
	this->m_pArray = array;
	this->m_Size = size;
	this->SortRun();

	cout<<"int Sort type data from small to large: ";
	for(int i = 0; i < m_Size; i++)
	{
		cout << m_pArray[i] << " ";	
	}
	cout<<endl;
}

  • Step 5: declare the single precision floating-point data sorting subclass FloatSort to inherit the abstract parent class
/* float_insort.h */

#ifndef _FLOAT_SORT_H_
#define _FLOAT_SORT_H_

#include <stdbool.h>
#include "sort.h"

class FloatSort:public Sort
{
public:
	FloatSort();
	virtual ~FloatSort();

	void Swap(int);		/* Rewriting float data interaction method */
	bool Judge(int);	/* Rewriting float data judgment method */
	void SortData(float*, int);
private:
	float *m_pArray;
};
#endif

  • Step 6: the single precision floating-point data sorting subclass FloatSort method is implemented to realize the sorting data type and sorting mode
/* float_sort.cpp */

#include <iostream>
#include "float_sort.h"

using namespace std;

FloatSort::FloatSort()
{
}

FloatSort::~FloatSort()
{
}

void FloatSort::Swap(int index)
{
	float temp;
	
	temp = m_pArray[index];
    m_pArray[index] = m_pArray[index+1];
    m_pArray[index+1] = temp;
}

bool FloatSort::Judge(int index)
{
	return m_pArray[index] < m_pArray[index+1];	/* Sort from large to small */
}

void FloatSort::SortData(float *array, int size)
{
	this->m_pArray = array;
	this->m_Size = size;
	this->SortRun();

	cout<<"float Sort type data from large to small: ";
	for(int i = 0; i < m_Size; i++)
	{
		cout << m_pArray[i] << " ";	
	}
	cout<<endl;
}

  • Step 7: the customer calls different subclass objects to realize the specified sorting function
/* client.cpp */
#include "sort.h"
#include "int_sort.h"
#include "float_sort.h"

int main(int argc, char **arv)
{
	int intArray[] = {1, 0, 3, 2, 5, 4, 7};
    int size = sizeof intArray / sizeof intArray[0];
    IntSort *intSort = new IntSort;
    intSort->SortData(intArray, size);
	delete intSort;

	float flaotArray[] = {1.0, 0.3, 1.2, 1.1, 5.4, 2.5, 3.3};
    size = sizeof flaotArray / sizeof flaotArray[0];
    FloatSort *floatSort = new FloatSort;
    floatSort->SortData(flaotArray, size);
	delete floatSort;
}
  • The last step is to write the Makefile file
VERSION 	=1.00
CC			=g++
DEBUG 		=
CFLAGS		=-Wall
SOURCES	 	=$(wildcard *.cpp)
INCLUDES  	=
LIB_NAMES 	=
LIB_PATH 	=
OBJ			=$(patsubst %.cpp, %.o, $(SOURCES))
TARGET		=client

#links
$(TARGET):$(OBJ)
	@mkdir -p output
	$(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) -o output/$(TARGET)$(VERSION)
	@rm -rf $(OBJ)
	
#compile
%.o: %.c
	$(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $< -o $@

.PHONY:clean
clean:
	@echo "Remove linked and compiled files......"
	rm -rf $(OBJ) $(TARGET) output 

Execution results:

acuity@ubuntu:/mnt/hgfs/LSW/STHB/design/template$ make
g++    -c -o float_sort.o float_sort.cpp
g++    -c -o int_sort.o int_sort.cpp
g++    -c -o client.o client.cpp
g++    -c -o sort.o sort.cpp
g++  float_sort.o  int_sort.o  client.o  sort.o   -o output/client1.00
acuity@ubuntu:/mnt/hgfs/LSW/STHB/design/template$ ls
client.cpp  float_sort.cpp  float_sort.h  int_sort.cpp  int_sort.h  Makefile  Makefile.bak  output  sort.cpp  sort.h
acuity@ubuntu:/mnt/hgfs/LSW/STHB/design/template$ ./output/client1.00 
int Sort type data from small to large: 0 1 2 3 4 5 7 
float Sort type data from large to small: 5.4 3.3 2.5 1.2 1.1 1 0.3 

6 Comparison between template mode and policy mode

6.1 comparison of differences


Similarities:

   both are flexible use of algorithms.


difference:

  • The template pattern is more important than stripping the algorithm steps. The common part is implemented by the abstract parent class, and the difference part is delayed to the child class. It is an algorithm
  • The strategy mode focuses on multiple algorithms that can be replaced with each other without affecting customers' use. It is aimed at multiple algorithms

   for example, for the above algorithm examples, the template mode decomposes a sorting algorithm into several steps, delays the difference step to the subclass implementation, and the sorting and sorting types of different types of data are implemented by the subclass. For the policy mode, this may be considered. A variety of sorting algorithms, such as bubble sorting, selection sorting, insertion sorting and so on, can be switched and selected freely.


6.2 advantages, disadvantages and application scenario selection

Comparison of advantages and disadvantages:

patternadvantageshortcoming
Template modeGood maintainability and vertical scalabilityHigh coupling, new functions need to add subclasses, and too many subclasses increase the complexity of the system
Strategy modeGood horizontal expansibility and high flexibilityThe customer must know all policy classes, which increases the complexity of the system

Scene selection

   template mode and strategy mode have their own advantages and disadvantages. The choice of which mode is an important and difficult one, which needs to be made according to the comprehensive consideration of specific business functions, function expansibility, industry characteristics and their own design experience. You can refer to the following choices.


sceneReference selection mode
Scene targeting is an algorithmTemplate mode
Multiple classes share common logic and algorithms, but some behave differentlyTemplate mode
Behavioral algorithms may change frequentlyTemplate mode
The customer is not sure what type of data to useTemplate mode
The scenario is targeted at a variety of algorithmsStrategy mode
Common algorithm and change algorithm scenarioStrategy mode
Public behavior and changing behavior scenariosStrategy mode

Keywords: Java C++ C#

Added by tpstudent on Fri, 15 Oct 2021 04:24:24 +0300