あなたが役に立つ戦略パターンについて知っている必要があるもの


最近、新しい言語を学びながら様々なコーディングパターンを再訪してきました.私の個人的な好みの1つのパターンは、戦略パターンです.戦略パターンの前提は、動作のファミリをカプセル化することです.カプセル化されるとき、我々は次に、実行時に使用するどのふるまいを選ぶことができます.
私の例では、Cのようにパターンを表示するつもりですが、これは広範囲の言語に適用できます.テキスト、PDF、イメージファイルからコンテンツを抽出するコードを作成しているとしましょう.行動の我々の家族は、したがって、テキスト抽出です.しかし、我々はファイルのタイプに基づいて異なった方法で内容を抽出したいです.
開始するには、インターフェイスと呼ばれるITextExtractor .
public interface ITextExtractor
{
    bool UseExtractor(string fileExtension);
    string[] ExtractContent(string filePath);
}
ドキュメントの種類ごとに、コンテンツを抽出したい新しいクラスを作成しますITextExtractor . 注意してくださいUseExtractor これを使用して、実行時にExtractorを選択します.先に行き、3つのテキスト抽出器を作成しましょう.

プレーンネストラクター
public class PlainTextExtractor : ITextExtractor
{
    public bool UseExtractor(string fileExtension)
    {
        return fileExtension.Equals("txt", StringComparison.OrdinalIgnoreCase);
    }

    public string[] ExtractContent(string filePath)
    {
        // extract the content here...
    }
}
PlainTextExtractorUseExtractor ファイル拡張子がtxtで終わる場合に限ります.

PDFTextTextTractor
public class PdfTextExtractor : ITextExtractor
{
    public bool UseExtractor(string fileExtension)
    {
        return fileExtension.Equals("pdf", StringComparison.OrdinalIgnoreCase);
    }

    public string[] ExtractContent(string filePath)
    {
        // extract the content here...
    }
}
PdfTextExtractorUseExtractor ファイル拡張子がPDFで終了する場合に限ります.

imagetextextractor
public class ImageTextExtractor : ITextExtractor
{
    private string[] _imageTypes = new[] { "png", "jpg", "jpeg", "tiff" };
    public bool UseExtractor(string fileExtension)
    {
        return _imageTypes.Any(it => it.Equals(fileExtension, StringComparison.OrdinalIgnoreCase);
    }

    public string[] ExtractContent(string filePath)
    {
        // extract the content here...
    }
}
ImageTextExtractorUseExtractor ファイル拡張子がPNG , JPG , JPEG , TIFFで終わる場合に限ります.これよりはるかに多くのイメージタイプがあります、しかし、これはあなたに我々が何をしているかについての考えを与えます.

陰謀ツ)_/実行時に戦略を選択するためのアプローチ
今、我々は様々なテキストを抽出している.ときに実行時に適切な抽出器を選択すると、頻繁にこのように書かれたコードを参照してください.
public class RunExtraction
{
    private PlainTextExtractor _plainTextExtractor;
    private PdfTextExtractor _pdfTextExtractor;
    private ImageTextExtractor _imageTextExtractor;

    public RunExtraction(PlainTextExtractor plainTextExtractor,
        PdfTextExtractor  pdfTextExtractor, ImageTextExtractor imageTextExtractor)
    {
        _plainTextExtractor = plainTextExtractor;
        _pdfTextExtractor = pdfTextExtractor;
        _imageTextExtractor = imageTextExtractor;
    }

    public string[] Extract(string filePath, string fileExtension)
    {
        if(_plainTextExtractor.UseExtractor(fileExtension))
        {
            return _plainTextExtractor.ExtractContent(filePath);
        }
        else if(_pdfTextExtractor.UseExtractor(fileExtension))
        {
            return _pdfTextExtractor.ExtractContent(filePath);
        }
        else if(_imageTextExtractor.UseExtractor(fileExtension))
        {
            return _imageTextExtractor.ExtractContent(filePath);
        }
        else
        {
            throw new Exception("unable to extract content");
        }        
    }
}
このコードは技術的には何の問題もない.しかし、それは将来に最も拡張可能ですか?どのような場合は、Word文書からコンテンツを抽出を開始する必要がありますか?
第一に、我々は新しいWordDocumentTextExtractor 実装するクラスITextExtractor .
public class WordDocumentTextExtractor : ITextExtractor
{
    private string[] _docTypes = new[] { "doc", "docx" };
    public bool UseExtractor(string fileExtension)
    {
        return _docTypes.Any(it => it.Equals(fileExtension, StringComparison.OrdinalIgnoreCase);
    }

    public string[] ExtractContent(string filePath)
    {
        // extract the content here...
    }
}
我々は、次に更新する必要がありますRunExtraction クラスを取るWordDocumentTextExtractor コンストラクタで.
private PlainTextExtractor _plainTextExtractor;
private PdfTextExtractor _pdfTextExtractor;
private ImageTextExtractor _imageTextExtractor;
private WordDocumentTextExtractor _wordDocumentTextExtractor;

public RunExtraction(PlainTextExtractor plainTextExtractor,
    PdfTextExtractor  pdfTextExtractor, ImageTextExtractor imageTextExtractor,
    WordDocumentTextExtractor wordDocumentTextExtractor)
{
    _plainTextExtractor = plainTextExtractor;
    _pdfTextExtractor = pdfTextExtractor;
    _imageTextExtractor = imageTextExtractor;
    _wordDocumentTextExtractor = wordDocumentTextExtractor;
}
それから、我々はもう一つを加える必要があるでしょうelse if Word文書をチェックする文.
else if(_wordDocumentTextExtractor.UseExtractor(fileExtension))
{
    return _wordDocumentTextExtractor.ExtractContent(filePath);
}
私たちが常に異なったタイプの文書から内容を抽出しなければならないならば、これは無作法になります.するたびに
  • 新しいテキスト抽出クラスを追加します.
  • 新しいクラスを通過するRunExtraction .
  • 更新else if 新しいドキュメントタイプを検出する条件.
  • 私の不安レベルは既に上がっています.別のアプローチが正しいに違いない?

    Q❂‿❂)P実行時の戦略選択へのアプローチ
    我々のために幸運で、我々は我々の戦略パターンで成功のために我々自身を準備しました.すべてのテキスト抽出器は、同じインターフェイスを実装ITextExtractor . そのインターフェースでUseExtractor . It returns true or false エクステンションに基づいて、各抽出器をサポートします.我々は両方の利点を活用することができます.
    まず、コンストラクタに渡されるものを変更しますRunExtraction .
    private ITextExtractor[] _extractors;
    
    public RunExtraction(ITextExtractor[] extractors)
    {
        _extractors = extractors;
    }
    
    Extractorの各タイプの具体的なクラスには、もはや渡されません.代わりにITextExtractor . これは新しいタイプの抽出器を追加したいときに渡される配列に追加するだけです.
    次に、私たちはExtract メソッドRunExtraction もはや使用しないif else if .... else if .
    public string[] Extract(string filePath, string fileExtension)
    {
        var extractor = _extractors.FirstOrDefault(e => e.UseExtractor(fileExtension));
        if(extractor != null)
        {
            return extractor.ExtractContent(filePath);
        }
        else
        {
            throw new Exception("unable to extract content");
        }
    }
    
    さようならelse if そして、こんにちは拡張性.我々RunExtract クラスはすぐに簡単に新しい文書のテキスト抽出をサポートすることができます.我々が我々を加えたい今WordDocumentTextExtractor 以下に必要な手順を示します.
  • 新しいテキスト抽出クラスを追加します.
  • 新しいクラスをExtractorの渡された配列に追加しますRunExtraction .

  • 結論
    ここでは、戦略パターンの基礎をカバーしている.
  • 同様の機能のインターフェイスを定義します.(テキスト抽出と同様)
  • その機能を実装するクラスを作成します.
  • 依存性の注入とインターフェイスを使用してロジッククラスを変更からシールします.
  • 動的に実行時に必要な機能を選択します.
  • その後、別の種類の具体的なクラスが追加されているので、将来的にあなたのコードが拡張可能になるのを見てください.

    アマゾンのWebサービスを学ぶ空腹?
    アマゾンのWebサービスを学ぶために空腹である多くの人々がいます.この事実に触発されて、私はそれを使用してAmazon Webサービスを学ぶことに焦点を当てコースを作成しました.静的なウェブサイトをホストして、確保して、届ける問題に集中します.あなたはS 3、APIゲートウェイ、Cloudfront、ラムダ、およびWAFのようなサービスを問題に解決策を構築することを学ぶ.
    AWS周辺の情報海がある.それは簡単に取得し、学習の進捗状況を作るのは簡単です.この問題を通じて、我々は情報をカットし、あなたの学習をスピードアップすることができます.この本とビデオコースの私の目標は、私があなたと学んだことを共有することです.
    面白いですか?着陸ページをチェックし、あなたのために働くパッケージを選択してください.here .