Java ENUMによる戦略設計パターン


戦略は、ソフトウェアがランタイムの間、アルゴリズムのファミリから1を選んだデザインパターンです.各アルゴリズムは自分のクラスで実装され、クライアントは交換可能になります.戦略デザインパターンを使用すると、クラスは異なる実装で、異なる方法で同じメソッドを実行できます.それは本のパターンの一つですDesign Patterns by Gamma et al .
たとえば、通勤する必要がある労働者を考慮してください.彼は車、オートバイ、自転車、または地下鉄で行くように、さまざまな戦略を使用することができます.クラスworker フィールドを持つtransport . とtransport 方法を持っているcommute . アルゴリズムを持つクラスはCar , Motorcycle , Bicycle , and Metro . それらを実装する必要がありますTransport インターフェイス.
メソッドへの呼び出しworker.transport.commute 別のアルゴリズムを使用することができます、私は、別の戦略を意味します.コンテキストは適切なアルゴリズムを選択する責任がないことに注意してください.これは1つの戦略を選択するクライアントによって行われます.コンテキストは、1つの戦略からメソッドを実行しますしたがって、コンテキストは実装に依存しません.
この記事では、Java ENUMで戦略デザインパターンを実装します.enumsほとんどのプログラマが知っているよりも機能があります.
また、このアプローチについてはOpen-Closed principle ちょっと.enumで実行時に新しい実装を追加することはできません.コードを更新する必要があります.コードを見ましょう.

バリデータの戦略
最初の例は、XML、JSON、YAML、またはCSVコンテンツのファイル形式バリデータです.従来の戦略実装では、それぞれのアルゴリズムに対して複数のクラスが必要です.enumでは、各定数であなたのビジネスルールを実装することができます.
public enum ValidatorStrategy {

    XML {
        @Override
        void doValidation(String content) {
            // The validation code goes here
            System.out.println("This is a XML content");
        }
    },
    JSON {
        @Override
        void doValidation(String content) {
            // The validation code goes here
            System.out.println("This is a JSON content");
        }
    },
    YAML {
        @Override
        void doValidation(String content) {
            // The validation code goes here
            System.out.println("This is a YAML content");
        }
    },
    CSV {
        @Override
        void doValidation(String content) {
            // The validation code goes here
            System.out.println("This is a CSV content");
        }
    };

    abstract void doValidation(String content);

}
Contextクラスは、クライアントからの戦略を受け取り、選択した戦略でアルゴリズムを実行します.
public class ValidatorContext {

    private ValidatorStrategy strategy;

    public ValidatorContext(ValidatorStrategy strategy) {
        this.strategy = strategy;
    }

    public void setValidator(ValidatorStrategy validator) {
        this.strategy = validator;
    }

    public void runValidation(String content) {
        strategy.doValidation(content);
    }

}
最後のコンポーネントは、検証戦略をコンテキストに渡すクライアントです.常にメソッドを呼び出すことを参照してくださいvalidator.runValidation , 戦略を設定した後.
ValidatorContext validator = new ValidatorContext(ValidatorStrategy.XML);
validator.runValidation("XML content");

validator.setValidator(ValidatorStrategy.YAML);
validator.runValidation("YAML content");

validator.setValidator(ValidatorStrategy.JSON);
validator.runValidation("JSON content");

日付フォーマッタ戦略
これは戦略デザインパターンの別の例です.さて、コンテクストクラスが実装クラスをストラテジークラスに渡すより複雑な状況があります.このように、依存エンジンを使用することが可能ですSpring .
public enum DateFormatterStrategy {
    BRAZIL {
        @Override
        public String doFormat(DateFormatterImpl formatter, Date date) {
            return formatter.formatBrazil(date);
        }
    },
    BELGIUM {
        @Override
        public String doFormat(DateFormatterImpl formatter, Date date) {
            return formatter.formatBelgium(date);
        }
    },
    US {
        @Override
        public String doFormat(DateFormatterImpl formatter, Date date) {
            return formatter.formatUS(date);
        }
    };

    public abstract String doFormat(DateFormatterImpl formatter, Date date);

}
実装クラスを以下に示します.これは、各ルールの日付をフォーマットするビジネスルールが含まれます.
public class DateFormatterImpl {

    private SimpleDateFormat sdfBrasil = new SimpleDateFormat("dd/MM/yyyy");
    private SimpleDateFormat sdfBelgium = new SimpleDateFormat("dd.MM.yyyy");
    private SimpleDateFormat sdfUS = new SimpleDateFormat("MM/dd/yyyy");

    public String formatBrazil(Date date) {
        return this.sdfBrasil.format(date);
    }

    public String formatBelgium(Date date) {
        return this.sdfBelgium.format(date);
    }

    public String formatUS(Date date) {
        return this.sdfUS.format(date);
    }

}
コンテキストクラスは以前と全く同じです.つまり、どんな目立つ違いもありません.
public class DateFormatterContext {

    private DateFormatterStrategy strategy;
    private DateFormatterImpl formatter = new DateFormatterImpl();

    public DateFormatterContext(DateFormatterStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(DateFormatterStrategy strategy) {
        this.strategy = strategy;
    }

    public String format(Date date) {
        return this.strategy.doFormat(formatter, date);
    }

}
最後のクライアントクラスは前のクラスと全く同じです.戦略を設定した後、メソッドを実行しますformatter.format , それから、選択された戦略は正しいアルゴリズムを実行するでしょう.
Date date = new Date();
DateFormatterContext formatter = new DateFormatterContext(DateFormatterStrategy.BELGIUM);
System.out.println("Belgium: " + formatter.format(date));

formatter.setStrategy(DateFormatterStrategy.BRAZIL);
System.out.println("Brazil: " + formatter.format(date));

formatter.setStrategy(DateFormatterStrategy.US);
System.out.println("US: " + formatter.format(date));

結論
Java ENUMは、異なるニーズにプログラマを助けることができる高度な機能を備えた便利な特別なタイプです.この場合,戦略設計パターンを実装した.このアプローチは単純さとより少ないクラスのような長所を持っています.しかし、また、短所があり、最も顕著なのは、それが開いて閉じた原則を少し中断するということです.
この投稿は当初公表されたStrategy Design Pattern with Java Enum .

参考文献
https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html