【デザインパターンシリーズ19】状態モードの原理と戦略モードおよび責任連鎖モードとの違いの分析

デザインパターンシリーズの概要

デザインパターン 航空券
3つのファクトリーモデル 搭乗口
戦略モード 搭乗口
委任モード 搭乗口
テンプレートメソッドパターン 搭乗口
オブザーバーモード 搭乗口
シングルトンモード 搭乗口
プロトタイプモード 搭乗口
エージェンシーモデル 搭乗口
デコレータモード 搭乗口
アダプターモード 搭乗口
ビルダーモード 搭乗口
責任連鎖モデル 搭乗口
フライウェイトモデル 搭乗口
コンビネーションモード 搭乗口
ファサードパターン 搭乗口
ブリッジモード 搭乗口
中間モデル 搭乗口
イテレーターモード 搭乗口
状態モード 搭乗口
通訳モード 搭乗口
メモモード 搭乗口
コマンドモード 搭乗口
ビジターモード 搭乗口
ソフトウェア設計の7つの原則と設計パターンの要約 搭乗口

序文

状態は開発者にとって非常に馴染み深いものです。通常の開発では、オブジェクトの状態は常に切り離せません。たとえば、レビュープロセスは連続状態フローのプロセスであり、注文プロセスも連続状態フローのプロセスであり、状態モードです。それは、私たちの州の流通プロセスにおけるビジネス処理ロジックをよりよく解決することです。

状態モードとは

ステートマシンパターンとも呼ばれるステートパターンを使用すると、オブジェクトの内部状態が変化しているときにオブジェクトの動作を変更して、クラスを変更したように見せることができます。

状態パターンでのクラスの動作は状態によって決定され、状態が異なれば動作も異なります。状態パターンの目的は、オブジェクトにその動作を一緒に変更させることです。

状態パターンの中核は、動作を各状態にバインドすることです。

さて、ふりをする時が再びここにあります:話は安いです、あなたにコードを見せてください、最初に非常に簡単な例を見てみましょう。

状態パターンの例

以下に、注文ステータスのフローに基づいた簡単な例を示します。注文には、支払い、受領、受領(完了)の3つのステータスしかないことを前提としています。

1.まず、すべての状態のすべての動作を定義する必要がある抽象状態クラスを作成します。

package com.zwx.design.pattern.state;

public abstract class AbstractOrderState {
    
    
    protected OrderContext orderContext;

    public AbstractOrderState(OrderContext orderContext) {
    
    
        this.orderContext = orderContext;
    }

    public abstract void payOrder();

    public abstract void deliver();

    public abstract void receiveGoods();
}

状態を切り替えるために使用されるOrderContextオブジェクトを統合することに注意してください。

2. 3つの状態があるため、抽象状態クラスを実装するために3つの具体的な状態クラスを作成します。

  • 保留中の支払いステータスカテゴリ:
package com.zwx.design.pattern.state;

public class WaitPaidOrderState extends AbstractOrderState {
    
    
    public WaitPaidOrderState(OrderContext orderContext) {
    
    
        super(orderContext);
    }

    @Override
    public void payOrder() {
    
    //相当于待支付的状态绑定了支付行为
        System.out.println("支付成功");
        this.orderContext.setState(this.orderContext.waitDeliver);//切换状态
    }

    @Override
    public void deliver() {
    
    
        System.out.println("对不起,请先付钱");
    }

    @Override
    public void receiveGoods() {
    
    
        System.out.println("对不起,请先付钱");
    }
}
  • 保留中の配信ステータスクラス:
package com.zwx.design.pattern.state;

public class WaitDeliverOrderState extends AbstractOrderState {
    
    
    public WaitDeliverOrderState(OrderContext orderContext) {
    
    
        super(orderContext);
    }

    @Override
    public void payOrder() {
    
    
        System.out.println("你已经付过钱了");
    }

    @Override
    public void deliver() {
    
    
        System.out.println("商品已发货并送达目的地");
        this.orderContext.setState(this.orderContext.receiveGoods);//切换状态
    }

    @Override
    public void receiveGoods() {
    
    
        System.out.println("请稍等,商品即将发货");
    }
}
  • 受け取ったステータスクラス:
package com.zwx.design.pattern.state;

public class ReceiveGoodsOrderState extends AbstractOrderState{
    
    
    public ReceiveGoodsOrderState(OrderContext orderContext) {
    
    
        super(orderContext);
    }

    @Override
    public void payOrder() {
    
    
        System.out.println("您已经付过钱啦,不要重复付钱哦");
    }

    @Override
    public void deliver() {
    
    
        System.out.println("商品已发货并送达,请不要重复发货");
    }

    @Override
    public void receiveGoods() {
    
    
        System.out.println("用户已收到商品,此次交易结束");
    }
}

各状態が動作にバインドされていることがわかり(複数のバインドもサポートできます)、対応する動作が処理された後、次の状態に流れ、現在の状態にない動作に対して対応するアクションを実行します。応答。

3.特定の状態間の切り替えを担当する状態コンテキスト環境クラスを作成します。

package com.zwx.design.pattern.state;

/**
 * @author zwx
 * @version 1.0
 * @date 2020/10/5
 * @since jdk1.8
 */
public class OrderContext {
    
    
    AbstractOrderState waitPaid;
    AbstractOrderState waitDeliver;
    AbstractOrderState receiveGoods;

    AbstractOrderState currState;//当前状态

    public OrderContext() {
    
    
        this.waitPaid = new WaitPaidOrderState(this);
        this.waitDeliver = new WaitDeliverOrderState(this);
        this.receiveGoods = new ReceiveGoodsOrderState(this);
        currState = waitPaid;
    }

    void setState(AbstractOrderState state){
    
    
        this.currState = state;
    }

    public void payOrder(){
    
    
        currState.payOrder();
    }


    public void deliver(){
    
    
        currState.deliver();
    }

    public void receiveGoods(){
    
    
        currState.receiveGoods();
    }
}

ご覧のとおり、このクラスには委任モードの影もあります。さまざまな動作が処理のために対応するオブジェクトに委任され、状態の切り替えのみを担当します。

4.最後に、テスト用の新しいテストクラスを作成します。

package com.zwx.design.pattern.state;

public class TestState {
    
    
    public static void main(String[] args) {
    
    
        OrderContext orderContext = new OrderContext();
        orderContext.payOrder();
        orderContext.deliver();
        orderContext.receiveGoods();
    }
}

出力結果は次のとおりです。

支付成功
商品已发货并送达目的地
用户已收到商品,此次交易结束

状態モードの役割

上記の例から、状態モデルには3つの主要な役割があると結論付けることができます。

  • コンテキスト:クライアントに必要なインターフェイスを定義し、現在の状態のインスタンスを内部的に維持し、特定の状態の切り替えを担当します。
  • 抽象状態の役割(状態):各状態で対応する動作を定義します。1つ以上の動作が存在する可能性があります。
  • 具体的な状態の役割(ConcreteState):状態に対応する動作を具体的に実現し、必要に応じて状態の切り替えを実現します。

状態モードと責任連鎖モード

この状態モードの実装は、1つのチェーンで処理される責任チェーンモードに似ているようです。特定のシナリオでは、2つのモードを置き換えることができると言えますが、2つのモードも本質的に異なります。

  • 状態モード:
    状態モードの次のノードは、各状態オブジェクトによってすでに理解されており、状態転送は内部で実行され、クライアントは決定できません。
  • 責任連鎖モデル
    の「リンク」上のオブジェクトは、次のノードプロセッサが誰であるかを認識していませんが、クライアント自体によって決定されます。

状態モードと戦略モード

状態モードと戦略モードの両方を使用して、多数のif / elseシナリオを排除できますが、本質的な違いがあります。戦略モードの各戦略は独立しており、相互に交換可能です。1つの戦略を選択することで需要を満たすことができ、クライアントが選択を行います。状態モードのクライアントは最初のノードのみを選択でき、後続のノードに自動的に流れます。各状態は全体であり、相互に置き換えることができる状態はありません。

状態モードのアプリケーションシナリオ

オブジェクトの状態を制御する条件式が複雑すぎる場合は、状態モードの使用を検討できます。状態の判定ロジックを異なる状態を表す一連のクラスに転送することで、複雑なロジックを簡略化してオブジェクトを作成できます。の動作はその状態に依存し、状態が変化すると動作が変化します。
状態モードは、主に次のシナリオで使用されます。

  • 1.状態の変化に応じてオブジェクトの動作を変更する必要がある場合。
  • 2.操作の状態に応じて大量のif / elseロジックを記述する必要がある場合

状態モードの長所と短所

利点:

  • 1.各状態を独立したオブジェクトとして設定することにより、コード内の多数のif / elseブランチが排除され、コードがより簡潔になり、保守が容易になります。
  • 2.さまざまな状態がさまざまなクラスで表されるため、数値や文字列で表される場合よりも状態の切り替えが直感的になり、変換の目的が明確になります。
  • 3.各ステータスクラスの責任は単一で明確であり、簡単に拡張できます。

不利益

  • 1.状態が多すぎると、クラスが拡張されます(実際、これはほとんどの設計パターンで一般的な問題でもあります)。
  • 2.状態モードの構造と実装は比較的複雑であるため、コードが混乱する可能性があります。
  • 3.状態切り替えをサポートする状態クラスは、開閉の原則に違反します。状態を変更するか、途中で状態を追加する必要がある場合、対応するソースコードを変更する必要があります。そうしないと、状態切り替えエラーが発生します。

総括する

この記事では、主に状態パターンの定義を紹介し、簡単な例で簡単な状態パターンを実装します。最後に、状態パターンと責任連鎖パターンを比較分析し、状態パターンと責任連鎖パターンの違いを明らかにします。

私に注意を払い、孤独なオオカミを学び、進歩してください

おすすめ

転載: blog.csdn.net/zwx900102/article/details/109202186