定义:允许一个对象在其内部状态变化时改变它的行为,对象看起来似乎修改了它所属的类。
类图:
说明:Context表示环境类,它定义了客户应用程序感兴趣的接口,并维护一个ConcreteState子类的实例,这个实例用于定义当前状态;State表示抽象状态类,它定义了一个接口以封装与Context的一个特定状态相关的行为;ConcreteStateA和ConcreteStateB表示具体状态类,每一个具体状态类实现一个与Context的一个状态相关的行为。
优点:
①.封装了状态的转换机制,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中
②.将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使用环境对象拥有不同的行为
③.允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块,可以避免使用庞大的条件语句来将业务方法状态转换代码交织在一起
④.可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数
缺点:
①.会增加系统中类和对象的个数,导致系统运行开销增大
②.结构与实现都较为复杂,如果使用不当将导致程序结构和代码混乱,增加系统设计的难度
③.对开闭原则的支持并不太好,增加新的状态类需要修改负责状态的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需要对应类的源代码。
适用环境:
①.对象的行为依赖于它的状态(如某些属性值),状态的改变将导致行为的改变
②.在代码中包含大量与对象状态有关的条件语句,这些条件语句的出现会导致代码可维护性和灵活性变差,不能方便地增加和删除状态,并且导致客户端类与类库之间的耦合增强
实例场景:状态实例模式之银行账户,我们定义了账户的三种状态:①如果账户中余额大于等于0,此时账户的状态为绿色,即为正常状态,表示既可以想账户存款,也可以从该账户取款。②如果账户中余额小于0,并且大于-1000,则账户的状态为黄色,即为欠费状态,表示既可以取款也可以存款③如果账户中余额小于-1000,那么账户的状态为红色,即为透支状态,此时用户只能向该账户存款,不能取款。
实例类图:
实例代码:
//状态类
/**
* 抽象状态类
* @author fly
*
*/
public abstract class AccountState{
protected Account account;
protected double balance;
public abstract void deposit(double amount);
public abstract void withdraw(double amount);
public abstract void stateCheck();
}
/**
* 绿色状态类:具体状态类
* @author fly
*
*/
public class GreenState extends AccountState{
public GreenState(AccountState state) {
// TODO Auto-generated constructor stub
this.balance =state.balance;
this.account = state.account;
}
public GreenState(double balance,Account account) {
// TODO Auto-generated constructor stub
this.balance = balance;
this.account = account;
}
@Override
public void deposit(double amount) {
// TODO Auto-generated method stub
this.balance += amount;
stateCheck();
}
@Override
public void withdraw(double amount) {
// TODO Auto-generated method stub
this.balance -= amount;
stateCheck();
}
@Override
public void stateCheck() {
// TODO Auto-generated method stub
if(balance>=-1000&&balance<0){
account.setState(new YellowState(this));
}else if(balance<-1000){
account.setState(new RedState(this));
}
}
}
/**
* 黄色状态类:具体状态类
* @author fly
*
*/
public class YellowState extends AccountState{
public YellowState(AccountState state) {
// TODO Auto-generated constructor stub
this.balance = state.balance;
this.account = state.account;
}
@Override
public void deposit(double amount) {
// TODO Auto-generated method stub
this.balance += amount;
stateCheck();
}
@Override
public void withdraw(double amount) {
// TODO Auto-generated method stub
this.balance -= amount;
stateCheck();
}
@Override
public void stateCheck() {
// TODO Auto-generated method stub
if(balance>=0){
account.setState(new GreenState(this));
}else if(balance<-1000){
account.setState(new RedState(this));
}
}
}
/**
* 红色状态类:具体状态类
* @author fly
*
*/
public class RedState extends AccountState{
public RedState(AccountState state) {
// TODO Auto-generated constructor stub
this.balance = state.balance;
this.account = state.account;
}
@Override
public void deposit(double amount) {
// TODO Auto-generated method stub
this.balance += amount;
stateCheck();
}
@Override
public void withdraw(double amount) {
// TODO Auto-generated method stub
System.out.println("账户被冻结,取款失败");
}
@Override
public void stateCheck() {
// TODO Auto-generated method stub
if(balance>=0){
account.setState(new GreenState(this));
}else if(balance>=-1000){
account.setState(new YellowState(this));
}
}
}
//银行账户
/**
* 银行账户:环境类
*
* @author fly
*
*/
class Account {
private AccountState state;
private String owner;
public Account(String owner,double init) {
// TODO Auto-generated constructor stub
this.owner = owner;
this.state = new GreenState(init, this);
System.out.println(this.owner+"开户,初始金额为"+init);
System.out.println("--------------------------------------------------");
}
public void setState(AccountState state){
this.state = state;
}
public void deposit(double amount){
System.out.println(this.owner+"存款"+amount);
state.deposit(amount);
System.out.println("现金余额为"+state.balance);
System.out.println("现在账户状态为"+state.getClass().getName());
System.out.println("--------------------------------------------------");
}
public void withdraw(double amount){
System.out.println(this.owner+"取款"+amount);
state.withdraw(amount);
System.out.println("现金余额为"+state.balance);
System.out.println("现在账户状态为"+state.getClass().getName());
System.out.println("--------------------------------------------------");
}
}
//客户端测试
public class Client {
public static void main(String[] args) {
Account account = new Account("fly", 5.0);
account.deposit(100);
account.withdraw(200);
account.deposit(1000);
account.withdraw(2000);
account.withdraw(100);
}
}
//运行结果: