Design Patterns Template Method Pattern

"Design Patterns" Basic Principles of Design Patterns
"Design Patterns" Singleton Patterns "
Design Patterns" Factory Patterns
"Design Patterns" Prototype Patterns "
Design Patterns" Builder Patterns "Design Patterns
" Adapter Patterns "Design
Patterns" Bridge Patterns
"Design Patterns" "Decorator Mode
" Design Mode" Composition Mode
"Design Mode" Appearance Mode "Design Mode"
Flyweight Mode "Design Mode" Proxy Mode "
Design Mode
" Template Method Mode
"Design Mode" Command Mode

Design Patterns Template Method Pattern

Definition :

  • The template method mode is also called the template mode. In an abstract class, the template that executes its method is publicly defined. Subclasses can rewrite the method implementation as needed, but the call will be performed in the manner defined in the abstract class.
  • The template method pattern is equivalent to defining the skeleton of an algorithm in an operation, and the implementation of specific steps is delayed to the subclass to define, so that the subclass can redefine some specific steps of the algorithm without changing the structure of an algorithm.
  • The basic idea is: the algorithm only exists in the parent class and is easy to modify. If you need to modify the algorithm, you only need to modify the template method of the parent class or some steps that have been implemented, and the subclass will inherit these modifications.

Roles covered by the template method pattern :

  • Abstract class : responsible for giving the outline and skeleton of an algorithm, which consists of a template method and several basic methods.
  • Concrete subclasses : implement the abstract methods and hook methods defined in the abstract class, which are the constituent steps of a top-level logic.

As the compositional role of the template pattern, the template method and basic method in the abstract class can be subdivided into :

  • Template method : defines the skeleton of the algorithm, and calls the basic methods it contains in a certain order.
  • Basic method : defines the specific steps to implement the algorithm, and the basic method can be divided into three types: (1) abstract method (2) concrete method (3) hook method : it has been implemented in the abstract class, including the logical method for judgment and empty methods that need to be overridden by subclasses. The general hook method is a logical method for judgment, the method name isXXX(), and the return value type is boolean.

Notes on the template method pattern :

  • Advantages : It achieves the maximum reuse of code, and the template method of the parent class and some steps that have been implemented will be inherited by the subclass and used directly. It not only unifies the algorithm, but also provides great flexibility. The template method of the parent class ensures that the structure of the algorithm remains unchanged, and the subclass provides the realization of some steps.
  • Disadvantages : **Each different implementation requires a subclass to implement, resulting in an increase in the number of classes and making the system even larger. **In addition, the abstract method in the parent class is implemented by the subclass, and the execution result of the subclass will affect the result of the parent class, which leads to a reverse control structure, which also increases the difficulty of code reading.
  • It should be noted that general template methods need to be finalmodified to prevent subclasses from overriding template methods.
  • The template method pattern is mainly used when the overall steps of the algorithm are fixed, but some parts of it are volatile. At this time, the template method pattern can be used to abstract the easily variable parts for subclasses to implement.

Template Method Pattern Class Diagram
insert image description here

Case background :

Students who often cook at home know that the basic steps of cooking are: pour oil —> heat oil —> put vegetables (also refers to meat) —> put seasonings —> stir fry and other steps, which should be the steps of most cooking Yes, just like a template, even students who are cooking for the first time only need to follow the steps of this template, and they can probably make an edible dish haha! Of course, as for the matching procedure of the taste, it depends on everyone's own control of the taste of the dish. This cooking scene in life is a typical application of the template method pattern.

The principle class diagram is as follows:
insert image description here

Cookkind:

public abstract class Cook {
    
    
	// 常量方法,不让子类去实现
    public final void cookProcess() {
    
    
        //第一步:倒油
        this.pourOil();
        //第二步:热油
        this.heatOil();
        //第三步:放菜
        this.pourThings();
        //第四步:放调料
        this.pourSauce();
        //第五步:翻炒
        this.fry();
    }

    public void pourOil() {
    
    
        System.out.println("倒油");
    }

    public void heatOil() {
    
    
        System.out.println("热油");
    }

    // 取决于做的是什么菜就放什么东西
    public abstract void pourThings();

    // 根据不同菜的特点,放入不同的调料
    public abstract void pourSauce();

    public void fry() {
    
    
        System.out.println("翻炒");
    }
}

StewedMeatkind:

public class StewedMeat extends Cook{
    
    
    @Override
    public void pourThings() {
    
    
        System.out.println("放大肉");
    }

    @Override
    public void pourSauce() {
    
    
        System.out.println("放酱油、生抽、盐、糖");
    }
}

FryEggplantkind:

public class FryEggplant extends Cook{
    
    
    @Override
    public void pourThings() {
    
    
        System.out.println("放大茄子");
    }

    @Override
    public void pourSauce() {
    
    
        System.out.println("放酱油、糖、酒、盐、鸡粉、生粉、八角、蒜头");
    }
}

Clientkind:

public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 做红烧肉
        StewedMeat stewedMeat = new StewedMeat();
        stewedMeat.cookProcess();
        System.out.println("-----------------------------");
        // 做红烧茄子
        FryEggplant fryEggplant = new FryEggplant();
        fryEggplant.cookProcess();
    }
}

If I want to make fried tofu at this time, the kind without any seasoning except cooking oil, so the step of adding seasoning can be omitted. However, the cooking steps are fixed in the cooking algorithm, what should I do? At this point, we can define a hook method in the abstract class to control whether the step of adding seasoning is needed.

The specific code is as follows:

public abstract class Cook {
    
    
    public final void cookProcess() {
    
    
        //第一步:倒油
        this.pourOil();
        //第二步:热油
        this.heatOil();
        //第三步:放菜
        this.pourThings();
        if (isOpen()) {
    
    
            //第四步:放调料
            this.pourSauce();
        }
        //第五步:翻炒
        this.fry();
    }

    public void pourOil() {
    
    
        System.out.println("倒油");
    }

    public void heatOil() {
    
    
        System.out.println("热油");
    }

    // 取决于做的是什么菜就放什么东西
    public abstract void pourThings();

    // 根据不同菜的特点,放入不同的调料
    public abstract void pourSauce();

    public void fry() {
    
    
        System.out.println("翻炒");
    }

    // 钩子方法
    public abstract boolean isOpen();
}

Application of template method pattern in JDK source code :

public abstract class InputStream implements Closeable {
    
    

	// 抽象方法,要求子类必须重写
	public abstract int read() throws IOException;
	
	public int read(byte b[]) throws IOException {
    
    
		return read(b, 0, b.length);
	}
	public int read(byte b[], int off, int len) throws IOException {
    
    
		if (b == null) {
    
    
			throw new NullPointerException();
		} else if (off < 0 || len < 0 || len > b.length - off) {
    
    
			throw new IndexOutOfBoundsException();
		} else if (len == 0) {
    
    
			return 0;
		}
		int c = read(); // 调用了无参的read方法,该方法是每次读取一个字节数据
		if (c == -1) {
    
    
			return -1;
		}
		b[off] = (byte)c;
		int i = 1;
		try {
    
    
			for (; i < len ; i++) {
    
    
				c = read();
				if (c == -1) {
    
    
					break;
				}
				b[off + i] = (byte)c;
			}
		} catch (IOException ee) {
    
    
		}	
		return i;
	}
}

The method of reading a byte array data has been defined in InputStreamthe parent class is to read one byte at a time, store it in the first index position of the array, and read lenbytes of data. The specific details of reading a byte of data are implemented by the InputStreaminherited subclass.

Guess you like

Origin blog.csdn.net/weixin_43252521/article/details/128524821