設計パターン-実際の状況へのテンプレートメソッドのエントリ

テンプレートメソッド

テンプレート方式とは

テンプレートメソッドのデザインアイデア

簡単に言うと、複数のサブクラスにアルゴリズムを実装するプロセスで、アプリケーション開発者が誤ったアルゴリズムプロセスを記述して、誤った結果をもたらすことを回避することです。クラスライブラリの開発者が固定アルゴリズムスケルトンを作成できるようにします(したがって、このモードは、アルゴリズムスケルトンが基本的に決定されるアプリケーションシナリオにのみ適応できます!)。すべてのクラスに共通のアルゴリズムとステップの一部をクラスライブラリに実装し、別のアプリケーション開発者に現在のシーンに適したいくつかのステップを記述させ、親クラスのスケルトンメソッドを呼び出してアルゴリズムを実装させます。

テンプレートメソッドのデザインパターンにはどのような種類のメソッドがありますか

まず、クラスライブラリによって実装され、アプリケーション開発者が変更できない固定メソッド

たとえば、次の実際の戦闘1銀行業務手順では、数値が取得され、評価を行うために業務が終了します。これらの2つのステップは、管理する必要のない異なるアプリケーションであるため、最終的に設定されます(Javaプログラミングでは、最終的なものです) c ++プログラミングの場合、関数実現をconstとして記述します!)。これらのプログラムは多くの場合、アプリケーション開発者とは何の関係もないコードです。アプリケーション開発者による不注意な変更を回避してアルゴリズムの誤った結果につながるのを防ぐために、finalに設定してください

2番目:クラスライブラリによって実装されますが、アプリケーション開発者は実際の状況に応じて変更を検討することもできます

たとえば、以下の実際の戦闘2のデータ分析プログラムでは、一部のアプリケーション(サブカテゴリ)のアプリケーションシナリオのデータを分析する前に処理する必要があります。ただし、一部のデータは直接分析できます。たとえば、Excelデータは多くの場合、ダウンロード後に直接処理できますが、一部の棒グラフデータは2次処理後に処理する必要があります。したがって、「フック関数」フックメソッドを設定できます。このメソッドは通常、ブール値(boolean / bool)を返します。ほとんどの状況を処理する必要がある場合、デフォルトでこのフックメソッドにfalseを返し、一部のアプリケーション開発者が処理を忘れてデータ分析プロセスに入るのを防ぎます。現在のデータが二次処理を必要としない場合、拡張サブクラスはこのメソッドをオーバーライドしてtrueを返す必要があります。

3番目:抽象クラスに関係なく、アプリケーション開発者が実装する抽象メソッド

Javaでは、抽象メソッドはキーワードabstractで表され、抽象ラベル付きメソッドを持つクラスは抽象クラスと呼ばれます。C ++の場合は、純粋仮想関数を設定することであり、純粋仮想関数を持つクラスは抽象クラスです。このメソッドを実装することはできません。親クラスで定義するだけで、コンパイラーはアプリケーションの開発者に、実際の状況に応じて抽象クラスを実装するよう強制します。実行時にポリモーフィズムの効果をプレイしましょう!

テンプレート方式を使用する利点

「開閉の原理」に沿って、サブクラスを呼び出す親クラスの効果を達成するためにアルゴリズムを修正してみましょう!
また、継承とポリモーフィズムを使用して、アルゴリズムスケルトンのコード再利用の効果を実現します。

テンプレート方法1に関連する実践:銀行業務処理手順

設計分析:

銀行取扱業務のアルゴリズム処理(スケルトン)には、以下のステップがあります
。①番号を取得
②業務を処理
業務終了後、業務の評価を行う

一部のプロセス(メソッド)は静的です。つまり、数値を取得してビジネスを終了するという2つのステップです。しかし、ビジネスを処理するプロセスは動的であり、ユーザーの役割が異なると、さまざまなビジネスを処理する必要があります。したがって、この動的プロセス(メソッド)と固定アルゴリズムのスケルトンのみを抽象化できます。ビジネスを処理する必要のあるさまざまな役割クラスがこの抽象クラスを継承し、サブクラスで処理する必要のあるビジネスを書き換えます。書き換えが終わったら、呼び出し側のメインクラスでアルゴリズムスケルトン全体のprocess()を呼び出します。ポリモーフィズムによれば、異なるサブカテゴリおよび実装された異なるビジネスプロシージャに応じて、同じアルゴリズムスケルトンで異なる結果が得られます。

私の抽象親クラス:BankTranscation


/**
* 这个抽象类作为模板方法的父类,完成银行业务
* @author 不会编程的小良
* @version 1.0
* */
abstract class BaseBankTranscation {
    
    

    static int ServerId = 1;

    public void takeNumber(){
    
    
        System.out.println("排队取号ing……");
    }

    /**
    * 这个抽象函数负责由子类根据具体业务完成重写
    * @author 不会编程的小良
    * @version 1.0
    * */
    public abstract void transcation();

    public void evalue(){
    
    
        System.out.println("第 " + ServerId + " 次服务结束,完成评分……");
    }

    public final void process(){
    
    
        System.out.println("开始第 " + ServerId + " 次服务!");
        takeNumber();
        transcation();
        evalue();
        ServerId++;
    }

}


さまざまなビジネスサブカテゴリ

/**
 * 这个子类负责重写父类BaseBankTranscation的方法transcation(),完成取款业务
 * @author 不会编程的小良
 * @version 1.0
 * */
class Deposite extends BaseBankTranscation {
    
    

    @Override
    public void transcation() {
    
    
        System.out.println("我要取款……");
    }
}

/**
 * 这个子类负责重写父类BaseBankTranscation的方法transcation(),完成存款业务
 * @author 不会编程的小良
 * @version 1.0
 * */
class Withdraw extends BaseBankTranscation {
    
    

    @Override
    public void transcation() {
    
    
        System.out.println("我要存款……");
    }
}

/**
 * 这个子类负责重写父类BaseBankTranscation的方法transcation(),完成转账业务
 * @author 不会编程的小良
 * @version 1.0
 * */
class Transfer extends BaseBankTranscation {
    
    

    @Override
    public void transcation() {
    
    
        System.out.println("我要转账……");
    }
}

メインクラスは各サブクラスのプロセスメソッドを呼び出してビジネス処理を完了します


/**
 * 这个主类负责完成各种银行业务的办理过程
 * @author 不会编程的小良
 * @version 1.0
 * */
public class TemplateMethod {
    
    

    public static void main(String[] args){
    
    

        int n = 3;
        BaseBankTranscation[] tran = new BaseBankTranscation[n];
        for(int i = 0;i < n;++i){
    
    
            switch (i % 3){
    
    
                case 0:
                    tran[i] = new Deposite();
                    break;
                case 1:
                    tran[i] = new Withdraw();
                    break;
                case 2:
                    tran[i] = new Transfer();
                    break;
                default:
                    break;
            }
        }
        for(BaseBankTranscation item : tran) {
    
    
            item.process();
        }

    }
}

実行結果は次のとおりです。

ここに画像の説明を挿入

テンプレートメソッドに関連する戦闘2:データ処理と分析のケース

設計分析:

このデータ処理と分析は、いくつかのステップに分かれています。

①データ取得(申請完了の抽象法)
②データを処理可能なモードに変換(フック法)
③データ解析(申請完了の抽象法)
④データ分析結果の表示(フック法)

親クラスBaseDataAnalysisの実装

abstract class BaseDataAnalysis {
    
    

    abstract void getData();

    void connvertData(){
    
    
        System.out.println("默认的数据转换方法……");
    }

    final void analysisData(){
    
    
        System.out.println("完成数据分析工作……");
    }

    void displayData(){
    
    
        System.out.println("默认的输出方式展示……");
    }

    boolean isValid(){
    
    
        return true;
    }

    void process(){
    
    
        getData();
        if(isValid()){
    
    
            connvertData();
        }
        analysisData();
        displayData();
    }

}

拡張サブクラスSubClassの実装

class SubClass extends BaseDataAnalysis {
    
    

    @Override
    void getData(){
    
    
        System.out.println("从JSON文件中获取数据……");
    }

    @Override
    void displayData(){
    
    
        System.out.println("以饼状图展示的方法展示……");
    }
}

メインクラスのメソッド実行のテスト

public class TemplateMethod {
    
    
    public static void main(String[] args){
    
    
        BaseDataAnalysis sub = new SubClass();
        sub.process();
    }
}

実行結果は次のとおりです。

ここに画像の説明を挿入

考えて練習する

問題の説明:

銀行のソフトウェアの利息計算プロセスは次のとおりです。

①システムがアカウントに従ってユーザー情報を照会する

②ユーザー情報からユーザーの種類を判断する

③ユーザーの種類によって、利息計算方法が異なります(現在、定期など)。

④興味を示す

私の解決策-銀行の金利クラス:

abstract class BankInterest {
    
    

    boolean isValidUser(String username, String password){
    
    
        if("jiangzhengliang".equals(username) && "123456".equals(password)) {
    
    
            System.out.println("账户:" + username);
            System.out.println("密码:" + password);
            return true;
        }
        else {
    
    
            return false;
        }
    }

    abstract void getAccountMethod();

    final void display(){
    
    
        System.out.println("显示利息……");
    }

    void process(String name, String psswd){
    
    
        if(isValidUser(name, psswd)){
    
    
            getAccountMethod();
            display();
        }
    }

}

ソリューションが拡張された現在および固定金利のサブカテゴリ

class CurrentAccount extends BankInterest {
    
    

    @Override
    void getAccountMethod() {
    
    
        System.out.println("我是活期贷款……");
    }
}

class SavingAccount extends BankInterest {
    
    

    @Override
    void getAccountMethod() {
    
    
        System.out.println("我是定期贷款……");
    }
}

私のソリューションはメインクラスをテストします

public class TemplateMethod {
    
    
    public static void main(String[] args){
    
    
        BankInterest bank1 = new CurrentAccount();
        bank1.process("jiangzhengliang", "123456");

        BankInterest bank2 = new SavingAccount();
        bank2.process("jiangzhengliang", "123456");
    }
}

テストの結果:

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/qq_44274276/article/details/107632746