Java設計モードのテンプレートメソッドモード


テンプレートメソッドモードの概要
テンプレートメソッド(Template method)は、その名の通り、いくつかのタスクを行う一般的なプロセスです.例えば、ネット上には自己紹介テンプレート、推薦状テンプレートがたくさんあります.つまり、最初と最後は差が少ないかもしれませんが、途中でお客様が修正して使用する必要があります.デザインモードは生活に由来し、テンプレート方法は似たようなシーンで誕生した.テンプレートメソッドとは、操作中のアルゴリズムフレームワークを書き、いくつかのステップをサブクラスに遅延させて実装することであり、サブクラスがアルゴリズムの構造を変更することなく、アルゴリズムの特定のステップを再定義することができる.
テンプレートメソッドの設計方法
テンプレート・メソッドは、通常、異なるサブクラスによって異なる実装がある可能性があるため、内部でサブクラスが実装する必要がある抽象メソッドを定義する抽象クラスを設計します.また、抽象クラスには1つ以上のテンプレートメソッド、すなわち固定されたフレームワークがあるべきであり、このメソッドの修飾子は通常finalと定義されている.これは、テンプレートが固定されており、修正できないと考えているため、サブクラスがこのテンプレートを上書きすることを防止するためである.この固定テンプレートメソッドの内部では、抽象メソッドが呼び出され、アルゴリズム全体のプロセスが一歩一歩実現されます.通常、サブクラスはこの抽象的な親を継承し、自分のビジネスロジックに基づいて抽象的な方法を実現します.
テンプレートメソッドの特徴
テンプレートメソッドは、あるビジネスの変化と不変を明確に画定し、あるビジネスのためにプロセスフレームワークを作成し、サブクラスに共通のコードを提供し、サブクラスの行為は完全に親によって制御され、コードのメンテナンス性と拡張性を実現した.親は修正を許さず、子は拡張することができ、設計モードの開閉原則によく合っている--修正に対して閉鎖し、拡張に対して開放する.
テンプレートメソッド設計モードと抽象クラス設計の違いに注意してください.抽象クラスという設計モードは親クラスがいくつかの抽象メソッドを定義し、サブクラスに実現させるため、サブクラスには通常より多くの自由空間があります.テンプレートメソッドでは、親がアルゴリズムフレームワークを定義し、子が親の抽象的なメソッドを実現するため、子の役割は親に影響を与えることができます.
テンプレートメソッドの適用例
背景紹介
お茶やコーヒーを入れるなど、今飲み物の製品を作るとします.お茶とコーヒーを入れる流れは大体4つのステップに分けることができて、第1は水を煮沸して、第2は原料を焙煎して、第3はカップの中に入れて、第4は調味料を加えます.通常、最初のステップと3番目のステップは同じ動作なので、親で直接方法を書くことができますが、2番目のステップと4番目のステップはお茶を入れるかコーヒーを入れるかで異なるので、抽象的な方法として設計され、サブクラスに実現させます.この4つのステップは全体的に飲料を入れる固定的な流れなので、私たちはこの4つのステップを1つの方法にカプセル化し、この方法の修飾子をfinalに設定して、サブクラスがそれを修正しないようにします.
テンプレートメソッド
テンプレートメソッドのコードを先に書きます.
package com.template;
/**
 *     
 *     ,           
 *   :    
 * @author zzw
 *
 */
public abstract class RefreshBeverage {
	
	/*
	 *          ,      
	 */
	//             
	public final void prepareBeverageTemplate() {
		//  1:    
		boilWater();
		
		//  2:    
		brew();
		
		//  3:    
		pourInCup();
		
		//  4:    (      ,       ,    )
		if(isCustomerWantCondiments()) {
			addCondiments();
		}
	}

	/*
	 * Hook,    
	 *            
	 *                     
	 *           
	 */
	protected boolean isCustomerWantCondiments() {
		//     
		return true;
	}

	//    ,     
	protected abstract void addCondiments();
	
	private void pourInCup() {
		//     
		System.out.println("    ");
	}

	//    ,     
	protected abstract void brew();
		
	private void boilWater() {
		//     
		System.out.println("    ");
	}

}

サブクラス実装
お茶を入れてコーヒーを飲む具体的な実現は異なるため、フック関数を使用してユーザーが調味料を加える必要があるかどうかを判断することができ、このようにプロセスをより人間的にすることができる.
お茶を入れる:
package com.template;
/**
 *          
 *   
 * @author zzw
 *
 */
public class TeaBeverage extends RefreshBeverage {

	
	@Override
	protected void addCondiments() {
		// TODO Auto-generated method stub

		System.out.println("      ");
	}

	@Override
	protected void brew() {
		// TODO Auto-generated method stub

		System.out.println("    ");
	}	
	

}

コーヒーを入れる:
package com.template;

public class CoffeeBeverage extends RefreshBeverage {

	@Override
	protected void addCondiments() {
		// TODO Auto-generated method stub
		
		System.out.println("      ");
	}

	@Override
	protected void brew() {
		// TODO Auto-generated method stub
		
		System.out.println("    ");
	}
	
}

中国茶は一般的に調味料を入れないので、ここで中国茶を1つ導入すれば、お茶を継承した上で、調味料を入れないかどうかを入れないようにすればよい.
package com.template;
/**
 *      
 *       
 *         
 *           
 * @author Administrator
 *
 */
public class ChineseTeaBeverage extends TeaBeverage {

	@Override
	protected boolean isCustomerWantCondiments() {
		// TODO Auto-generated method stub
		return false;
	}

	
}

フック関数
フックは実際にはメッセージを処理するプログラムセグメントであり、システム呼び出しによってシステムに掛けられます.フックプログラムは、特定のメッセージが発行されるたびに、目的ウィンドウに到達する前に、メッセージ、すなわちフック関数が先に制御権を取得する.このときフック関数は、メッセージを加工(変更)してもよいし、処理せずにメッセージを伝達し続けてもよいし、メッセージの伝達を強制的に終了させることもできる.各タイプのフックに対してシステムによってフックチェーンを維持し、最近取り付けられたフックはチェーンの開始に配置され、最初に取り付けられたフックは最後に配置され、つまり後に加えられた先に制御権を得る.本明細書で述べたように、調味料を添加するかどうかはフック関数であり、調味料を添加するかどうかに決定権を有する.特定のスレッドを指定すると、スレッド専用フックになります.空に指定すると、グローバルフックになります.ここで、グローバルフック関数はDLL(ダイナミックリンクライブラリ)に含める必要があり、スレッド専用フックは実行可能ファイルに含めることもできます.制御権を得たフック関数は、メッセージの処理が完了した後、メッセージを伝達し続けるためには、別のSDKのAPI関数CallNextHookExを呼び出して伝達しなければならない.フック関数はまた、直接TRUEに戻ることによってメッセージを破棄し、メッセージの伝達を阻止することもできる.
テンプレートメソッドモードの使用シーン
テンプレート法は、アルゴリズムの不変の部分を一度に実現し、可変の部分をサブクラスに残して実現するために使用することができる.サブクラスの共通コード部分は親クラスに抽出され、コードの重複作成を防止しなければならない.サブクラスの拡張を制御します.テンプレートメソッドでは、特定のポイントでフック関数を呼び出すことしか許可されません.これにより、これらのポイントでのみ拡張が許可されます.