デザインパターン7:ステートモード(状態)

ソフトウェア開発プロセスでは、いくつかのオブジェクトのアプリケーションは状況に応じて異なる動作を行うことができ、我々はステートフルオブジェクトと呼ばれるこのオブジェクト、および1つの影響オブジェクトまたは複数の動的挙動のプロパティを呼び出します状態と呼ばれます。オブジェクトの状態は、外部イベントと対話するとき、それは彼らの行動が変わりますのでことを、その内部状態を変更します。人間の感情は幸せな時間と悲しい時間を持っているなど、さまざまな感情が異なる振る舞いを持っている、もちろん、外の世界も、自分の気分の変化に影響を与えます。

このオブジェクトは、プログラミングの状態を持っている、伝統的な解決策は以下のとおりです。考慮し、これらすべての状況がすべて可能であり、異なる状況の文は使用状態の決意をすれば、そうでない場合、処理。しかし、オブジェクトの多くの州では、手順が非常に複雑になります。そして、「開閉の原則」に反している新しいのif-else文を追加するには新しいステータスを追加するためのプログラムの拡大を助長されていません。

上記の問題であれば、「状態モード」解消に良いことができます。元の複雑なロジックが決意を簡素化することができるように、状態間のクラスのシリーズに、抽出された「論理の分析」、オブジェクトの状態遷移の条件式制御が複雑すぎる場合、関連する:思想は、状態モデルが解決されます。

状態パターンの定義と特性

定義された状態(ステート)モード:被験者の状態、異なる状態にオブジェクトを抽出し、複雑な「決定論理」、オブジェクトの状態を可能にするときに内部状態変化の挙動を変更します。

状態モデルは、次のようにその主な利点は、オブジェクトの行動パターンです。

  1. 状態モデルは、ローカライズされた状態の動作に特定の状態に関連し、異なる状態の挙動は、会う分離「単一責任の原則を。」
  2. オブジェクト間の相互依存性を減らします。ターゲット異なる状態が明確になる別の状態遷移の導入を行い、オブジェクト間の相互依存性を低減します。
  3. 延長の賛成で。新しいサブクラスの定義によって簡単に新しい状態と遷移を追加します。


モードの状態の主な欠点は次の通りです。

  1. システムを使用してクラスとオブジェクトの数は必然的状態パターンを増加させます。
  2. 状態モデルの構造と実装がより複雑な、不適切な使用は、プログラム構造とコードならば混乱を招くことができます。

建築と状態パターンの実装

異なる状態オブジェクトの環境のパッケージによって変化挙動へのオブジェクトモデルの状態、意図は、彼らの行動が変更されたときにオブジェクトがその内部状態を変更することです。今、私たちは基本的な構造と実装を分析する必要があります。

1.構造モデル

ステート・モードは、次の主要な役割が含まれています。

  1. 環境(コンテキスト)の役割:またコンテキストと呼ばれる、クライアントにとって関心のインタフェースを定義し、ハンドルへのオブジェクトの現在の動作状態に関連する現在の状況と委託状態を維持します。
  2. 抽象状態(ステート)の役割:行動に対応する特定のパッケージ環境状態オブジェクトのインタフェースを定義します。
  3. 特定の状態(コンクリート州)の役割:行動に対応する抽象状態。


図1に示す構造。

                   図状態パターン構造
 

実現の2モード

次のような状態のパターンコードは次のとおりです。

package state;
public class StatePatternClient
{
    public static void main(String[] args)
    {       
        Context context=new Context();    //创建环境       
        context.Handle();    //处理请求
        context.Handle();
        context.Handle();
        context.Handle();
    }
}
//环境类
class Context
{
    private State state;
    //定义环境类的初始状态
    public Context()
    {
        this.state=new ConcreteStateA();
    }
    //设置新状态
    public void setState(State state)
    {
        this.state=state;
    }
    //读取状态
    public State getState()
    {
        return(state);
    }
    //对请求做处理
    public void Handle()
    {
        state.Handle(this);
    }
}
//抽象状态类
abstract class State
{
    public abstract void Handle(Context context);
}
//具体状态A类
class ConcreteStateA extends State
{
    public void Handle(Context context)
    {
        System.out.println("当前状态是 A.");
        context.setState(new ConcreteStateB());
    }
}
//具体状态B类
class ConcreteStateB extends State
{
    public void Handle(Context context)
    {
        System.out.println("当前状态是 B.");
        context.setState(new ConcreteStateA());
    }
}

次のようにプログラムの結果は以下のとおりです。 

当前状态是 A.
当前状态是 B.
当前状态是 A.
当前状态是 B.

アプリケーション状態パターンの例

[例1]「モデル状態」に状態遷移プログラムの生徒の成績を設計します。

分析:この例では、生徒のスコアが60未満の「失敗」の時間が共有されたときに、「中」と「優れた」3つの状態が、「失敗」状態、スコアはタイムシェアリングのための60に相当し、90分未満より以上の場合、「媒体を含みます「スコアよりも大きいかのように90時分割に等しいときの状態は、」優れた「状態、われわれはこのプログラムを達成するために状態モデルを使用しています。

まず、環境属性、属性名と現在のスコアステータス属性とサブサブトラクション法addScore(INTX)を含み、抽象メソッドにcheckState(の現在の状態を確認する抽象状態クラス(AbstractState)、)の定義、そして、いいえ」の定義「国家クラスLowState、」中間「状態クラスMiddleStateと」優れた「状態クラスHighStateを渡し、彼らはにcheckState()メソッドを達成し、特定の状態のカテゴリーである、自分の状態を確認する責任がある、との変換に応じて、および環境の最後に、定義(オブジェクトの現在の状態との減算ポイントのメソッドを含むScoreContext)は、この方法により、顧客クラスの性能状態を変更するために、(INTスコア)を加えます。図2は、構成図です。
 

                    状態遷移は、生徒の成績のプログラムの構造を図式化

コードは以下の通りであります:

package state;
public class ScoreStateTest
{
    public static void main(String[] args)
    {
        ScoreContext account=new ScoreContext();
        System.out.println("学生成绩状态测试:");
        account.add(30);
        account.add(40);
        account.add(25);
        account.add(-15);
        account.add(-25);
    }
}
//环境类
class ScoreContext
{
    private AbstractState state;
    ScoreContext()
    {
        state=new LowState(this);
    }
    public void setState(AbstractState state)
    {
        this.state=state;
    }
    public AbstractState getState()
    {
        return state;
    }   
    public void add(int score)
    {
        state.addScore(score);
    }
}
//抽象状态类
abstract class AbstractState
{
    protected ScoreContext hj;  //环境
    protected String stateName; //状态名
    protected int score; //分数
    public abstract void checkState(); //检查当前状态
    public void addScore(int x)
    {
        score+=x;       
        System.out.print("加上:"+x+"分,\t当前分数:"+score );
        checkState();
        System.out.println("分,\t当前状态:"+hj.getState().stateName);
    }   
}
//具体状态类:不及格
class LowState extends AbstractState
{
    public LowState(ScoreContext h)
    {
        hj=h;
        stateName="不及格";
        score=0;
    }
    public LowState(AbstractState state)
    {
        hj=state.hj;
        stateName="不及格";
        score=state.score;
    }
    public void checkState()
    {
        if(score>=90)
        {
            hj.setState(new HighState(this));
        }
        else if(score>=60)
        {
            hj.setState(new MiddleState(this));
        }
    }   
}
//具体状态类:中等
class MiddleState extends AbstractState
{
    public MiddleState(AbstractState state)
    {
        hj=state.hj;
        stateName="中等";
        score=state.score;
    }
    public void checkState()
    {
        if(score<60)
        {
            hj.setState(new LowState(this));
        }
        else if(score>=90)
        {
            hj.setState(new HighState(this));
        }
    }
}
//具体状态类:优秀
class HighState extends AbstractState
{
    public HighState(AbstractState state)
    {
        hj=state.hj;
        stateName="优秀";
        score=state.score;
    }           
    public void checkState()
    {
        if(score<60)
        {
            hj.setState(new LowState(this));
        }
        else if(score<90)
        {
            hj.setState(new MiddleState(this));
        }
    }
}

次のようにプログラムの結果は以下のとおりです。 

学生成绩状态测试:
加上:30分,    当前分数:30分,    当前状态:不及格
加上:40分,    当前分数:70分,    当前状态:中等
加上:25分,    当前分数:95分,    当前状态:优秀
加上:-15分,    当前分数:80分,    当前状态:中等
加上:-25分,    当前分数:55分,    当前状态:不及格

「ステータスパターン」設計条件変換プログラム[実施例2]マルチスレッド。

分析:その状態遷移規則に示すように、関連するメソッド呼び出しまたはイベントトリガ他の状態に変換するときの状態および死亡状態をブロッキング5つの状態、すなわち、新たな状態のため、レディ状態、走行状態が存在するマルチスレッド、各状態が発生します図3は、図2に示します。
 

                      スレッドの状態遷移図
図3の状態遷移図をスレッド。


今、新しい状態(新)、レディ状態(Runnableを)、(ランニング)動作状態、遮断状態であり、図3に示した各状態のタイプ、のための特定の状態の設計(抽象クラ​​スの状態(TheadState)を定義ブロック)と死状態(DEAD)、各状態は、MR(新)で初期状態に(はThreadContext)環境、そのメソッドをトリガする状態遷移を有し、トリガ方法を提供する、スレッドは、図に示す状態遷移図である。4図のプログラム構造。
 

                          図変換プログラムスレッド状態の構造
図の構成図4変換プログラムスレッド状態


コードは以下の通りであります:

package state;
public class ThreadStateTest
{
    public static void main(String[] args)
    {
        ThreadContext context=new ThreadContext();
        context.start();
        context.getCPU();
        context.suspend();
        context.resume();
        context.getCPU();
        context.stop();
    }
}
//环境类
class ThreadContext
{
    private ThreadState state;
    ThreadContext()
    {
        state=new New();
    }
    public void setState(ThreadState state)
    {
        this.state=state;
    }
    public ThreadState getState()
    {
        return state;
    }   
    public void start()
    {
        ((New) state).start(this);
    }
    public void getCPU()
    {
        ((Runnable) state).getCPU(this);
    }
    public void suspend()
    {
        ((Running) state).suspend(this);
    }
    public void stop()
    {
        ((Running) state).stop(this);
    }
    public void resume()
    {
        ((Blocked) state).resume(this);
    }
}
//抽象状态类:线程状态
abstract class ThreadState
{
    protected String stateName; //状态名
}
//具体状态类:新建状态
class New extends ThreadState
{
    public New()
    {       
        stateName="新建状态";
        System.out.println("当前线程处于:新建状态.");   
    }
    public void start(ThreadContext hj)
    {
        System.out.print("调用start()方法-->");
        if(stateName.equals("新建状态"))
        {
            hj.setState(new Runnable());
        }
        else
        {
            System.out.println("当前线程不是新建状态,不能调用start()方法.");
        }
    }   
}
//具体状态类:就绪状态
class Runnable extends ThreadState
{
    public Runnable()
    {       
        stateName="就绪状态";
        System.out.println("当前线程处于:就绪状态.");   
    }
    public void getCPU(ThreadContext hj)
    {
        System.out.print("获得CPU时间-->");
        if(stateName.equals("就绪状态"))
        {
            hj.setState(new Running());
        }
        else
        {
            System.out.println("当前线程不是就绪状态,不能获取CPU.");
        }
    }   
}
//具体状态类:运行状态
class Running extends ThreadState
{
    public Running()
    {       
        stateName="运行状态";
        System.out.println("当前线程处于:运行状态.");   
    }
    public void suspend(ThreadContext hj)
    {
        System.out.print("调用suspend()方法-->");
        if(stateName.equals("运行状态"))
        {
            hj.setState(new Blocked());
        }
        else
        {
            System.out.println("当前线程不是运行状态,不能调用suspend()方法.");
        }
    }
    public void stop(ThreadContext hj)
    {
        System.out.print("调用stop()方法-->");
        if(stateName.equals("运行状态"))
        {
            hj.setState(new Dead());
        }
        else
        {
            System.out.println("当前线程不是运行状态,不能调用stop()方法.");
        }
    }
}
//具体状态类:阻塞状态
class Blocked extends ThreadState
{
    public Blocked()
    {       
        stateName="阻塞状态";
        System.out.println("当前线程处于:阻塞状态.");   
    }
    public void resume(ThreadContext hj)
    {
        System.out.print("调用resume()方法-->");
        if(stateName.equals("阻塞状态"))
        {
            hj.setState(new Runnable());
        }
        else
        {
            System.out.println("当前线程不是阻塞状态,不能调用resume()方法.");
        }
    }   
}
//具体状态类:死亡状态
class Dead extends ThreadState
{
    public Dead()
    {
        stateName="死亡状态";
        System.out.println("当前线程处于:死亡状态.");   
    }   
}

次のようにプログラムの結果は以下のとおりです。 

当前线程处于:新建状态.
调用start()方法-->当前线程处于:就绪状态.
获得CPU时间-->当前线程处于:运行状态.
调用suspend()方法-->当前线程处于:阻塞状态.
调用resume()方法-->当前线程处于:就绪状态.
获得CPU时间-->当前线程处于:运行状态.
调用stop()方法-->当前线程处于:死亡状态.

 

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

一般的に使用される状態モデルは、次の場合に考慮することができます。

  • オブジェクトの振る舞いは、その状態に依存し、それは実行時に状態に応じてその動作を変更しなければならないときは、使用状態モードを考慮することができます。
  • 含まれる大きな分岐構造を操作し、オブジェクトの分岐の状態を判断した場合。

拡張ステータスモード

いくつかの場合において、複数のオブジェクトは、次に、環境状態のセット、フライ級、番組共有のためのオブジェクトのセット状態において特にそれらを導入する必要性を共有する必要があるかもしれない、構造が図5に示されています。
 

              図共有状態設定モード
 


分析:モデルを除いて、共有状態が状態を保存するHashMapのは、以下のようにコードがある特定の状態、必要な場合、から取得することができる関連したクラスの環境で増加します。

package state;
import java.util.HashMap;
public class FlyweightStatePattern
{
    public static void main(String[] args)
    {
        ShareContext context=new ShareContext(); //创建环境       
        context.Handle(); //处理请求
        context.Handle();
        context.Handle();
        context.Handle();
    }
}
//环境类
class ShareContext
{
    private ShareState state;
    private HashMap<String, ShareState> stateSet=new HashMap<String, ShareState>();
    public ShareContext()
    {
        state=new ConcreteState1();
        stateSet.put("1", state);
        state=new ConcreteState2();
        stateSet.put("2", state);
        state=getState("1");
    }
    //设置新状态
    public void setState(ShareState state)
    {
        this.state=state;
    }
    //读取状态
    public ShareState getState(String key)
    {
        ShareState s=(ShareState)stateSet.get(key);
        return s;
    }
    //对请求做处理
    public void Handle()
    {
        state.Handle(this);
    }
}
//抽象状态类
abstract class ShareState
{
    public abstract void Handle(ShareContext context);
}
//具体状态1类
class ConcreteState1 extends ShareState
{
    public void Handle(ShareContext context)
    {
        System.out.println("当前状态是: 状态1");
        context.setState(context.getState("2"));
    }
}
//具体状态2类
class ConcreteState2 extends ShareState
{
    public void Handle(ShareContext context)
    {
        System.out.println("当前状态是: 状态2");
        context.setState(context.getState("1"));
    }
}

 次のようにプログラムの結果は以下のとおりです。

当前状态是: 状态1
当前状态是: 状态2
当前状态是: 状态1
当前状态是: 状态2

 

公開された136元の記事 ウォンの賞賛6 ビュー1544

おすすめ

転載: blog.csdn.net/weixin_42073629/article/details/104437847