现在的位置: 首页 > 综合 > 正文

设计模式之十 — 状态(State)模式

2013年08月06日 ⁄ 综合 ⁄ 共 6131字 ⁄ 字号 评论关闭

【1】基本概念

          状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

【2】简单分析

         我们先来看下该设计模式的UML的结构图

【3】如何用Java语言实现该设计模式

本篇文章以一个贴近现实生活的例子来展示如何使用该设计模式,以方便大家尽快的掌握状态设计模式。例子:如某人去银行新开一个账户,该账户可以用来存钱或者取钱,我们可以以账户中的总资金来判断显示某用户账户的状态:红色状态(RedState),银色状态(SliverState),金色状态GoldState)。其实就好比银行中根据我们存储卡中的资金来给客户某种身份的识别,例如普通用户,VIP客户,公司客户....等等。

我们先看下该实例Demo的结构图:

3.1 State.java 源码:

package com.andyidea.patterns.concretestate;

import com.andyidea.patterns.context.Account;

/**
 * State类,抽象状态类,定义一个接口以封装
 * 与Context的一个特定状态相关的行为。
 * @author Andy
 *
 */
public abstract class State {
	
    protected Account account;
    protected double balance;

    protected double interest;
    protected double lowerLimit;
    protected double upperLimit;

    //-------------Properties------------------//
    public Account getAccount() {
		return account;
	}
	public void setAccount(Account account) {
		this.account = account;
	}
	
	public double getBalance() {
		return balance;
	}
	public void setBalance(double balance) {
		this.balance = balance;
	}
	//------------------------------------------//
	
	/**存入金额*/
	public abstract void deposit(double amount);
	/**支出金额*/
    public abstract void withdraw(double amount);
    /**利息*/
    public abstract void payInterest();

}

3.2  RedState.java源码:

package com.andyidea.patterns.concretestate;


/**
 * 用户账户状态:RedState
 * @author Andy
 * ConcreteState类,具体状态,每一个子类实现一个与
 * Context的一个状态相关的行为。
 */
public class RedState extends State {
	
	private double serviceFee;

	public RedState(State state) {
		this.balance = state.getBalance();
		this.account = state.getAccount();
		initialize();
	}

	 /** 模拟初始化基础数据*/
	private void initialize() {
		interest = 0.0;
		lowerLimit = -100.0;
		upperLimit = 0.0;
		serviceFee = 15.00;
	}

	@Override
	public void deposit(double amount) {
	      balance += amount;
	      stateChangeCheck();
	}

	@Override
	public void withdraw(double amount) {
	      amount = amount - serviceFee;
	      System.out.println("No funds available for withdrawal!");
	}

	@Override
	public void payInterest() {
		// No interest is paid
	}
	
	/** 状态检测 */
	private void stateChangeCheck() {
		if (balance > upperLimit) {
			account.setState(new SilverState(this));
		}
	}

}

SliverState.java源码:

package com.andyidea.patterns.concretestate;

import com.andyidea.patterns.context.Account;

/**
 * 用户账户状态:SilverState
 * @author Andy
 * ConcreteState类,具体状态,每一个子类实现一个与
 * Context的一个状态相关的行为。
 */
public class SilverState extends State {
	
    public SilverState(State state){
    	this(state.balance,state.account);
    }

    public SilverState(double balance, Account account){
      this.balance = balance;
      this.account = account;
      initialize();
    }

    /** 模拟初始化基础数据*/
    private void initialize(){
      interest = 0.0;
      lowerLimit = 0.0;
      upperLimit = 1000.0;
    }

	@Override
	public void deposit(double amount) {
	      balance += amount;
	      stateChangeCheck();
	}

	@Override
	public void withdraw(double amount) {
	      balance -= amount;
	      stateChangeCheck();
	}

	@Override
	public void payInterest() {
	      balance += interest * balance;
	      stateChangeCheck();
	}
	
	/** 状态检测 */
    private void stateChangeCheck(){
      if (balance < lowerLimit){
    	  account.setState(new RedState(this));
      }
      else if (balance > upperLimit){
    	  account.setState(new GoldState(this));
      }
    }

}

GoldState.java源码:

package com.andyidea.patterns.concretestate;

import com.andyidea.patterns.context.Account;

/**
 * 用户账户状态:GoldState
 * @author Andy
 * ConcreteState类,具体状态,每一个子类实现一个与
 * Context的一个状态相关的行为。
 */
public class GoldState extends State {
	
    public GoldState(State state){
    	this(state.balance, state.account);
    }

    public GoldState(double balance, Account account){
      this.balance = balance;
      this.account = account;
      initialize();
    }

    /** 模拟初始化基础数据*/
    private void initialize(){
      interest = 0.05;
      lowerLimit = 1000.0;
      upperLimit = 10000000.0;
    }

	@Override
	public void deposit(double amount) {
	     balance += amount;
	     stateChangeCheck();
	}

	@Override
	public void withdraw(double amount) {
	      balance -= amount;
	      stateChangeCheck();
	}

	@Override
	public void payInterest() {
	      balance += interest * balance;
	      stateChangeCheck();
	}
	
	/** 状态检测 */
	private void stateChangeCheck() {
		if (balance < 0.0) {
			account.setState(new RedState(this));
		} else if (balance < lowerLimit) {
			account.setState(new SilverState(this));
		}
	}

}

3.3 Account.java类源码:

package com.andyidea.patterns.context;

import com.andyidea.patterns.concretestate.SilverState;
import com.andyidea.patterns.concretestate.State;

/**
 * Context类,维护一个ConcreteState子类的实例
 * 这个实例定义当前的状态。
 * @author Andy
 *
 */
public class Account {
	
    private State state;
    private String owner;

    public Account(String owner){
      // 新开账户默认为 Silver状态
      this.owner = owner;
      this.state = new SilverState(0.0, this);
    }

    public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

	public void deposit(double amount) {
		state.deposit(amount);
		System.out.println(owner + " Deposited  " + amount);
		System.out.println(owner + " Balance =  " + state.getBalance());
		System.out.println("Status = " + state.getClass().getSimpleName());
		System.out.println("==============================================");
	}
 
    public void withdraw(double amount){
        state.withdraw(amount);
        System.out.println(owner + " Withdrew  " + amount);
        System.out.println(owner + " Balance =  " + state.getBalance());
        System.out.println("Status = " + state.getClass().getSimpleName());
        System.out.println("==============================================");
    }
 
    public void payInterest(){
        state.payInterest();
        System.out.println(owner + " Interest Paid  ");
        System.out.println(owner + " Balance =  " + state.getBalance());
        System.out.println("Status = " + state.getClass().getSimpleName());
        System.out.println("==============================================");
    }

}

3.4 客户端测试类 StateClient.java 类源码:

package com.andyidea.patterns;

import com.andyidea.patterns.context.Account;

public class StateClient {
	
	public static void main(String[] args) {
	      // 新开一个银行账户
	      Account account = new Account("Andy.Chen");

	      // 存取款等系列操作
	      account.deposit(500.0);
	      account.deposit(300.0);
	      account.deposit(550.0);
	      account.payInterest();
	      account.withdraw(2000.00);
	      account.withdraw(1100.00);
	}

}

【4】下面我们来看下程序运行的结果:

Andy.Chen Deposited  500.0
Andy.Chen Balance =  500.0
Status = SilverState
==============================================
Andy.Chen Deposited  300.0
Andy.Chen Balance =  800.0
Status = SilverState
==============================================
Andy.Chen Deposited  550.0
Andy.Chen Balance =  1350.0
Status = GoldState
==============================================
Andy.Chen Interest Paid  
Andy.Chen Balance =  1417.5
Status = GoldState
==============================================
Andy.Chen Withdrew  2000.0
Andy.Chen Balance =  -582.5
Status = RedState
==============================================
No funds available for withdrawal!
Andy.Chen Withdrew  1100.0
Andy.Chen Balance =  -582.5
Status = RedState
==============================================

【5】总结:

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。

本文为 Andy.Chen 原创,欢迎大家继续关注Me的博文,欢迎大家转载,谢谢!

抱歉!评论已关闭.