JAva設計モードの状態モード


一、状態モードの紹介
多くの場合、1つのオブジェクトの動作は、1つ以上の変化するプロパティに依存します.これらのプロパティは、ステータスオブジェクトと呼ばれ、このオブジェクトはステータスオブジェクトと呼ばれます.ステータスオブジェクトの場合、その動作はそのステータスに依存します.例えば、部屋を予約する場合は、その部屋が空いている場合にのみ予約できます.この部屋にチェックインしたい場合も、その部屋を予約した場合や空いている場合だけです.このようなオブジェクトに対して、外部イベントがインタラクティブになると、その内部状態が変化し、彼の行為も変化します.
では、ステータスモードとは何でしょうか.ステータスモードとは、オブジェクトが内部状態が変化したときにその動作を変更することを許可し、オブジェクトがクラスを変更したように見えます.
状態モードは、状態オブジェクトモード(Pattern of Objects for States)とも呼ばれ、状態モードはオブジェクトの動作モードである.
一言で述べると,状態モードは研究対象の挙動を異なる状態対象にパッケージし,各状態対象は抽象状態クラスのサブクラスに属する.ステータスモードは、オブジェクトの内部ステータスが変化すると、その動作も変化することを意味します.
ステータス・モードの役割は、次のとおりです.
環境(Context)ロールは、クライアントが関心を持つインタフェースを定義し、特定のステータスクラスのインスタンスを保持するコンテキストにもなります.この特定のステータスクラスのインスタンスは、この環境オブジェクトの既存のステータスを示します.
抽象状態(State)ロール:環境(Context)オブジェクトの特定の状態に対応する動作をカプセル化するインタフェースを定義します.
特定のステータス(ConcreteState)ロール:各特定のステータスクラスは、環境(Context)のステータスに対応する動作を実現します.
シーンを使用:
1.オブジェクトの動作は、その状態(属性)に依存し、その状態の変化に応じて関連する動作を変更することができる.
2、コードにはオブジェクトの状態に関する条件文がたくさん含まれています.
二、実例のプレゼンテーション
1、業務ニーズ
1つのオンライン投票システムの応用を考慮して、同じユーザーが1票しか投票できないことを制御することを実現するには、1人のユーザーが繰り返し投票し、投票回数が5回を超えると、悪意のあるブラシ票と判定され、そのユーザーの投票資格を取り消すには、もちろん同時に彼が投票した票を取り消さなければならない.1人のユーザーの投票回数が8回を超えると、ブラックリストに入り、再登録やシステム使用が禁止されます.
状態モードを用いて実現するには,まず投票過程の様々な状態を定義する必要があり,以上の説明から,通常投票,反復投票,悪意のある投票,ブラックリストへのアクセスの4つの状態に大別される.次に、Contextに相当する投票管理オブジェクトを作成します.
2、抽象状態クラスを定義し、具体的に状態クラスを実現する
public interface VoteState {
    /**
     *          
     * user       
     * voteItem       
     * voteManager         ,                 ,
     *           
     */
    public void vote(String user,String voteItem,VoteManager voteManager);
}
具体的な状態類——正常投票
public class NormalVoteState implements VoteState {


    @Override
    public void vote(String user, String voteItem, VoteManager voteManager) {
        //    ,        
        voteManager.getMapVote().put(user, voteItem);
        System.out.println("      ");
    }


}
具体的な状態類——繰り返し投票
public class RepeatVoteState implements VoteState {


    @Override
    public void vote(String user, String voteItem, VoteManager voteManager) {
        //    ,      
        System.out.println("       ");
    }


}
具体的な状態類——悪意のあるブラシ切符
public class SpiteVoteState implements VoteState {


    @Override
    public void vote(String user, String voteItem, VoteManager voteManager) {
        //     ,         ,       
        String str = voteManager.getMapVote().get(user);
        if(str != null){
            voteManager.getMapVote().remove(user);
        }
        System.out.println("        ,      ");
    }


}
具体的な状態類——ブラックリスト
public class BlackVoteState implements VoteState {


    @Override
    public void vote(String user, String voteItem, VoteManager voteManager) {
        //      ,      
        System.out.println("     ,           ");
    }


}
3、環境クラスの定義
public class VoteManager {
    //        
    private VoteState state = null;
    //         ,Map<String,String>  Map<    ,     >
    private Map<String,String> mapVote = new HashMap<String,String>();
    //        ,Map<String,Integer>  Map<    ,     >
    private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>();
    /**
     *          Map
     */
    public Map<String, String> getMapVote() {
        return mapVote;
    }
    /**
     *   
     * user       
     * voteItem         
     */
    public void vote(String user,String voteItem){
        //1.          
        //                
        Integer oldVoteCount = mapVoteCount.get(user);
        if(oldVoteCount == null){
            oldVoteCount = 0;
        }
        oldVoteCount += 1;
        mapVoteCount.put(user, oldVoteCount);
        //2.          ,           
        //       、    、             
        if(oldVoteCount == 1){
            state = new NormalVoteState();
        }
        else if(oldVoteCount > 1 && oldVoteCount < 5){
            state = new RepeatVoteState();
        }
        else if(oldVoteCount >= 5 && oldVoteCount <8){
            state = new SpiteVoteState();
        }
        else if(oldVoteCount > 8){
            state = new BlackVoteState();
        }
        //                
        state.vote(user, voteItem, this);
    }
}
4、テストクラスの作成
public class Client {


    public static void main(String[] args) {
        
        VoteManager vm = new VoteManager();
        for(int i=0;i<9;i++){
            vm.vote("chen","A");
        }
    }


}
、テスト結果
      
       
       
       
        ,      
        ,      
        ,      
        ,      
     ,           

上記の例に基づいて,状態の変換は基本的に内部挙動であり,主に状態モード内部で維持されることが分かる.例えば、投票者に対しては、いつでも投票を行うが、投票管理対象者の処理は必ずしも同じではなく、投票の回数によって状態を判断し、状態によって異なる処理を選択する.
三、まとめ
ステータスモードのメリットとデメリット
メリット:
1、変換ルールが封入されている.
2、列挙可能な状態であり、列挙状態の前に状態の種類を確定する必要がある.
3、ある状態に関係するすべての動作を1つのクラスに配置し、オブジェクトの状態を変えるだけでオブジェクトの動作を変えることができる新しい状態を簡単に追加することができる.
4、状態変換ロジックを状態オブジェクトと一体的に合成することを許可し、ある巨大な条件文ブロックではない.
5、複数の環境オブジェクトに1つの状態オブジェクトを共有させることで、システム内のオブジェクトの数を減らすことができる.
欠点:
1、ステータスモードの使用は必然的にシステムクラスとオブジェクトの個数を増加させる.
2、状態モードの構造と実現は複雑で、不適切な使用はプログラム構造とコードの混乱を招く.
3、ステータスモードは「開閉原則」のサポートがあまりよくなく、ステータスを切り替えることができるステータスモードに対して、新しいステータスクラスを追加するには、ステータス変換を担当するソースコードを修正する必要があります.そうしないと、新しいステータスに切り替えることができません.また、ステータスクラスの動作を変更するには、対応するクラスのソースコードも変更する必要があります.