《JAVA與模式》之狀態模式

來源:互聯網
上載者:User
文章目錄
  •   原始碼
  •   原始碼

在閻宏博士的《JAVA與模式》一書中開頭是這樣描述狀態(State)模式的:

  狀態模式,又稱狀態物件模式(Pattern of Objects for States),狀態模式是對象的行為模式。

  狀態模式允許一個對象在其內部狀態改變的時候改變其行為。這個對象看上去就像是改變了它的類一樣。


狀態模式的結構

  用一句話來表述,狀態模式把所研究的對象的行為封裝在不同的狀態物件裡,每一個狀態物件都屬於一個抽象狀態類的一個子類。狀態模式的意圖是讓一個對象在其內部狀態改變的時候,其行為也隨之改變。狀態模式的示意性類圖如下所示:

  狀態模式所涉及到的角色有:

  ●  環境(Context)角色,也成上下文:定義用戶端所感興趣的介面,並且保留一個具體狀態類的執行個體。這個具體狀態類的執行個體給出此環境對象的現有狀態。

  ●  抽象狀態(State)角色:定義一個介面,用以封裝環境(Context)對象的一個特定的狀態所對應的行為。

  ●  具體狀態(ConcreteState)角色:每一個具體狀態類都實現了環境(Context)的一個狀態所對應的行為。

  原始碼

  環境角色類

public class Context {    //持有一個State類型的對象執行個體    private State state;    public void setState(State state) {        this.state = state;    }    /**     * 使用者感興趣的介面方法     */    public void request(String sampleParameter) {        //轉調state來處理        state.handle(sampleParameter);    }}

  抽象狀態類

public interface State {    /**     * 狀態對應的處理     */    public void handle(String sampleParameter);}

  具體狀態類

public class ConcreteStateA implements State {    @Override    public void handle(String sampleParameter) {                System.out.println("ConcreteStateA handle :" + sampleParameter);    }}
public class ConcreteStateB implements State {    @Override    public void handle(String sampleParameter) {                System.out.println("ConcreteStateB handle :" + sampleParameter);    }}

  用戶端類

public class Client {    public static void main(String[] args){        //建立狀態        State state = new ConcreteStateB();        //建立環境        Context context = new Context();        //將狀態設定到環境中        context.setState(state);        //請求        context.request("test");    }}

  從上面可以看出,環境類Context的行為request()是委派給某一個具體狀態類的。通過使用多態性原則,可以動態改變環境類Context的屬性State的內容,使其從指向一個具體狀態類變換到指向另一個具體狀態類,從而使環境類的行為request()由不同的具體狀態類來執行。

使用情境

  考慮一個線上投票系統的應用,要實現控制同一個使用者只能投一票,如果一個使用者反覆投票,而且投票次數超過5次,則判定為惡意刷票,要取消該使用者投票的資格,當然同時也要取消他所投的票;如果一個使用者的投票次數超過8次,將進入黑名單,禁止再登入和使用系統。

  要使用狀態模式實現,首先需要把投票過程的各種狀態定義出來,根據以上描述大致分為四種狀態:正常投票、反覆投票、惡意刷票、進入黑名單。然後建立一個投票管理對象(相當於Context)。

  系統的結構圖如下所示:

  

  原始碼

  抽象狀態類

public interface VoteState {    /**     * 處理狀態對應的行為     * @param user    投票人     * @param voteItem    投票項     * @param 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("進入黑名單,將禁止登入和使用本系統");    }}

  環境類

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;    }    /**     * 投票     * @param user    投票人     * @param 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);    }}

  用戶端類

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

  運行結果如下:

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.