デザインパターン-戦略的デザインパターン

1はじめに

実生活では、特定の目標を達成するために複数の戦略を選択できる状況に遭遇することがよくあります。たとえば、旅行では飛行機に乗る、電車に乗る、自転車に乗る、自家用車を運転するなど、スーパーマーケットのプロモーションなどがあります。割引を利用して商品を配達することができます。、ポイントやその他の方法を送信します。

ソフトウェア開発でも同様の状況が発生することがよくあります。特定の機能を実装するためのアルゴリズムや戦略が複数ある場合は、データの並べ替え戦略でのバブリングなど、さまざまな環境や条件に応じて、さまざまなアルゴリズムや戦略を選択して機能を完成させることができます。選択ソート、挿入ソート、バイナリツリーソートなど。

複数の条件付き遷移ステートメントを使用して実現(ハードコーディング)すると、条件ステートメントが非常に複雑になるだけでなく、元のコードを変更してアルゴリズムを追加、削除、または置換する必要があります。これは、保守が難しく、原則に違反します。開閉の。この問題は、戦略モデルを採用すればうまく解決できます。

2.戦略モデルの定義と特徴

ストラテジーモードの定義:このモードは、一連のアルゴリズムを定義し、各アルゴリズムをカプセル化して、それらを相互に置き換えることができるようにします。アルゴリズムの変更は、アルゴリズムを使用する顧客に影響を与えません。ストラテジーモードは、オブジェクト動作モードに属し、アルゴリズムをカプセル化し、アルゴリズムの使用とアルゴリズムの実現の責任を分離し、これらのアルゴリズムを管理するためにさまざまなオブジェクトに委任します。

戦略モードの主な利点は次のとおりです。

  1. 複数の条件ステートメントを維持するのは簡単ではありません。戦略モードを使用すると、if ... elseステートメント、switch ... caseステートメントなどの複数の条件ステートメントの使用を回避できます。
  2. 戦略パターンは、一連の再利用可能なアルゴリズムファミリを提供します。継承を適切に使用すると、アルゴリズムファミリの共通コードを親クラスに転送して、コードの重複を回避できます。
  3. 戦略モードは、同じ動作のさまざまな実現を提供でき、顧客はさまざまな時間またはスペースの要件に応じてさまざまな戦略を選択できます
  4. ストラテジーモードは、開始と終了の原則を完全にサポートし、元のコードを変更せずに新しいアルゴリズムを柔軟に追加できます。
  5. ストラテジーモードでは、アルゴリズムの使用が環境クラスに配置され、アルゴリズムの実現が特定のストラテジークラスに移動され、2つの分離が実現されます。

主な欠点は次のとおりです。

  1. クライアントは、適切なアルゴリズムクラスを適切なタイミングで選択するために、すべての戦略アルゴリズムの違いを理解する必要があります。
  2. ストラテジーモードでは、多くのストラテジークラスが作成されるため、メンテナンスが難しくなります。

3.戦略モデルの構造と実現

ストラテジーモードは、アルゴリズムのセットを準備し、このアルゴリズムのセットを抽象ストラテジークラスのサブクラスとして一連のストラテジークラスにカプセル化することです。戦略モデルの焦点は、アルゴリズムの実装方法ではなく、プログラム構造がより柔軟になり、保守性とスケーラビリティが向上するようにこれらのアルゴリズムを編成する方法です。次に、その基本構造と実装方法を分析します。

1.モデルの構造

戦略モードの主な役割は次のとおりです。

  1. 抽象戦略(Strategy)クラス:パブリックインターフェイスを定義し、さまざまなアルゴリズムがこのインターフェイスをさまざまな方法で実装します。環境アクターはこのインターフェイスを使用して、通常はインターフェイスまたは抽象クラスによって実装されるさまざまなアルゴリズムを呼び出します。
  2. 具体的な戦略(具体的な戦略)クラス:抽象戦略によって定義されたインターフェイスを実装し、特定のアルゴリズムの実装を提供します。
  3. 環境(コンテキスト)クラス:最終的にクライアントによって呼び出される戦略クラスへの参照を保持します。

ここに画像の説明を挿入します

2.パターンの実装

public class StrategyPattern {
    
    
    public static void main(String[] args) {
    
    
        Context c = new Context();
        Strategy s = new ConcreteStrategyA();
        c.setStrategy(s);
        c.strategyMethod();
        System.out.println("-----------------");
        s = new ConcreteStrategyB();
        c.setStrategy(s);
        c.strategyMethod();
    }
}

//抽象策略类
interface Strategy {
    
    
    public void strategyMethod();    //策略方法
}

//具体策略类A
class ConcreteStrategyA implements Strategy {
    
    
    public void strategyMethod() {
    
    
        System.out.println("具体策略A的策略方法被访问!");
    }
}

//具体策略类B
class ConcreteStrategyB implements Strategy {
    
    
    public void strategyMethod() {
    
    
        System.out.println("具体策略B的策略方法被访问!");
    }
}

//环境类
class Context {
    
    
    private Strategy strategy;

    public Strategy getStrategy() {
    
    
        return strategy;
    }

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

    public void strategyMethod() {
    
    
        strategy.strategyMethod();
    }
}

特定のストラテジーAのストラテジーメソッドにアクセスします!
-----------------
特定のストラテジーBのストラテジーメソッドにアクセスします!

4.ストラテジーモードの適用例

【例1】「毛ガニ」調理におけるストラテジーモードの適用。

分析:毛ガニには多くの方法がありますが、戦略モデルの応用を紹介する例として、蒸し毛ガニと蒸し毛カニの2つの方法を取り上げます。

まず、ヘアリークラブを処理するための抽象戦略クラス(CrabCooking)を定義します。これには、抽象調理メソッドCookingMethod()が含まれます。次に、抽象化を実装する蒸しカニ(SteamedCrabs)と編組カニ(BraisedCrabs)の特定の戦略クラスを定義します。ストラテジークラスでは、このプログラムは完成した結果グラフを表示するため、特定のストラテジークラスはJLabelのサブクラスとして定義されます。最後に、調理ストラテジーの設定と選択を含むキッチン(キッチン)環境クラスが定義されます。カスタマークラスは、キッチンクラスを通じて調理戦略を取得し、調理結果グラフをフォームに表示します。図2にその構造を示します。

ここに画像の説明を挿入します

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    public class CrabCookingStrategy implements ItemListener {
    
    
        private JFrame f;
        private JRadioButton qz, hs;
        private JPanel CenterJP, SouthJP;
        private Kitchen cf;    //厨房
        private CrabCooking qzx, hsx;    //大闸蟹加工者  
        CrabCookingStrategy() {
    
    
            f = new JFrame("策略模式在大闸蟹做菜中的应用");
            f.setBounds(100, 100, 500, 400);
            f.setVisible(true);
            f.setResizable(false);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            SouthJP = new JPanel();
            CenterJP = new JPanel();
            f.add("South", SouthJP);
            f.add("Center", CenterJP);
            qz = new JRadioButton("清蒸大闸蟹");
            hs = new JRadioButton("红烧大闸蟹");
            qz.addItemListener(this);
            hs.addItemListener(this);
            ButtonGroup group = new ButtonGroup();
            group.add(qz);
            group.add(hs);
            SouthJP.add(qz);
            SouthJP.add(hs);
            //---------------------------------
            cf = new Kitchen();    //厨房
            qzx = new SteamedCrabs();    //清蒸大闸蟹类
            hsx = new BraisedCrabs();    //红烧大闸蟹类
        }
        public void itemStateChanged(ItemEvent e) {
    
    
            JRadioButton jc = (JRadioButton) e.getSource();
            if (jc == qz) {
    
    
                cf.setStrategy(qzx);
                cf.CookingMethod(); //清蒸
            } else if (jc == hs) {
    
    
                cf.setStrategy(hsx);
                cf.CookingMethod(); //红烧
            }
            CenterJP.removeAll();
            CenterJP.repaint();
            CenterJP.add((Component) cf.getStrategy());
            f.setVisible(true);
        }
        public static void main(String[] args) {
    
    
            new CrabCookingStrategy();
        }
    }
    //抽象策略类:大闸蟹加工类
    interface CrabCooking {
    
    
        public void CookingMethod();    //做菜方法
    }
    //具体策略类:清蒸大闸蟹
    class SteamedCrabs extends JLabel implements CrabCooking {
    
    
        private static final long serialVersionUID = 1L;
        public void CookingMethod() {
    
    
            this.setIcon(new ImageIcon("src/strategy/SteamedCrabs.jpg"));
            this.setHorizontalAlignment(CENTER);
        }
    }
    //具体策略类:红烧大闸蟹
    class BraisedCrabs extends JLabel implements CrabCooking {
    
    
        private static final long serialVersionUID = 1L;
        public void CookingMethod() {
    
    
            this.setIcon(new ImageIcon("src/strategy/BraisedCrabs.jpg"));
            this.setHorizontalAlignment(CENTER);
        }
    }
    //环境类:厨房
    class Kitchen {
    
    
        private CrabCooking strategy;    //抽象策略
        public void setStrategy(CrabCooking strategy) {
    
    
            this.strategy = strategy;
        }
        public CrabCooking getStrategy() {
    
    
            return strategy;
        }
        public void CookingMethod() {
    
    
            strategy.CookingMethod();    //做菜  
        }
    }

ここに画像の説明を挿入します

【例2】韶関からブ源への移動モードを実現するための戦略モデル。

分析:韶関からブ源への移動には、電車、車、自動運転など、いくつかの方法があります。したがって、この例には戦略モードの方が適しています。図4にその構造を示します。

ここに画像の説明を挿入します

5.戦略モードのアプリケーションシナリオ

ストラテジーモードは多くの場所で使用されます。たとえば、Java SEのコンテナレイアウト管理は典型的な例です。JavaSEの各コンテナには、ユーザーが選択できる複数のレイアウトがあります。プログラム設計では、通常、戦略パターンは次の状況で使用されます。

  1. システムがいくつかのアルゴリズムの1つを動的に選択する必要がある場合、各アルゴリズムを戦略クラスにカプセル化できます。
  2. クラスは複数の動作を定義し、これらの動作はこのクラスの操作で複数の条件ステートメントの形式で表示されます。各条件分岐をそれぞれの戦略クラスに移動して、これらの条件ステートメントを置き換えることができます。
  3. システム内のアルゴリズムが互いに完全に独立しており、特定のアルゴリズムの実装の詳細を顧客から隠す必要がある場合。
  4. アルゴリズムを使用する顧客がその操作のデータを知らないようにシステムが要求する場合、戦略モードを使用して、アルゴリズムに関連するデータ構造を非表示にすることができます。
  5. 複数のクラスは、パフォーマンス動作のみが異なります。ストラテジーモードを使用して、実行時に実行する特定の動作を動的に選択できます。

6.戦略モードの拡張

ストラテジーモードを使用するシステムでは、ストラテジーが多いと、すべてのストラテジーアルゴリズムのクライアント管理が非常に複雑になります。環境クラスでストラテジーファクトリーモードを使用してこれらのストラテジークラスを管理すると、クライアントの作業の複雑さが増します。大幅に削減されます。、その構造図を図5に示します。
ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/saienenen/article/details/112671093