上一篇:设计模式(十七)——备忘录模式

下一篇:设计模式(十九)——策略模式

一、概述

官方解释:Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.(当一个对象在状态改变时允许其改变行为,这个对象看起来像改变了其类。)

我的理解:

设计的时候,将State引用注入到Context类中,状态设置判断一般用boolean或int;

运行的时候,客户端通过调用Context类对象的方法,间接操作State类,即完成了状态变化,又很好的在客户端隐藏了State类。

参与者:Context环境类、State状态类(抽象状态类、具体状态类)

类图:

设计模式(十八)——状态模式_设计模式

二、代码

代码1——开门关门实例(boolean类型变量为状态判断) 代码2——银行存款取款实例(int类型变量为状态判断)

代码1——开门关门实例(boolean类型变量为状态判断):

package mypackage;


public class DesignPatternDemo {

	public static void main(String[] args) {

		Door door=new Door(true);
		
		
		
		door.request();
		door.request();
		door.request();
	}

}
abstract class State{
	protected Door door;
	public abstract void handle();  
	public abstract void stateCheck();
}
class OpenState extends State{
    
	@Override
	public void handle() {
		//具体操作  handle方法
		door.isOpen=!door.isOpen;
		stateCheck();
	}
	public  OpenState(State state) {
this.door=state.door;
	}
	public  OpenState(Door door) {
this.door=door;
	}
	@Override
	public String toString() {
		
		return "OpenState";
	}
	@Override
	public void stateCheck() {
		//状态更新	
		if (door.isOpen) {
			door.setState(new OpenState(this));
		}else {
			door.setState(new CloseState(this));
		}
	}
	
}
class CloseState extends State{

	@Override
	public void handle() {
		//具体操作  handle方法
		door.isOpen=!door.isOpen;
		stateCheck();
	}
	public  CloseState(Door door) {
		this.door=door;
	}
	public  CloseState(State state) {
		this.door=state.door;
	}
	@Override
	public String toString() {
		
		return "CloseState";
	}
	@Override
	public void stateCheck() {
		//状态更新	
		if (door.isOpen) {
			door.setState(new OpenState(this));
		}else {
			door.setState(new CloseState(this));
		}
	}
	
}

class Door{
	private State state;   //state引用注入环境类Context
	public  boolean isOpen;  //通过判断value的变化来改变状态    一般是int或boolean类型
	public void setState(State state){
		this.state=state;
	}
	public State getState(){
		return this.state;
	}
	public void request(){
		state.handle();//调用state类方法
		System.out.println(state);
	}
	
	public Door(boolean isOpen){
		this.isOpen=isOpen;
		if (isOpen) {
			state=new OpenState(this);
		}else {
			state=new CloseState(this);
		}
		
		
	
	}
}

输出1:

CloseState
OpenState
CloseState

代码2——银行存款取款实例(int类型变量为状态判断):

package mypackage;

public class DesignPatternDemo {
	public static void main(String[] args) {
Account account=new Account("张三",0.0);  //新建环境类  Account 银行账户
account.deposit(1000);     //将state注入到Account类中        通过操作Account间接操作state
account.withdraw(2000);

account.deposit(3000);
account.withdraw(4000);
account.withdraw(1000);
	}
}

class Account { // 账户类 就是环境类Context
	private AccountState state; // 注入state 就要调用state的方法 deposit withdraw
								// computeInterest checkState
	private String owner;
	private double balance = 0;// 余额
    public Account(String owner,double balance){
	this.owner=owner;
	this.balance=balance;	
	this.state=new NormalState(this);  //初试为正常状态
	System.out.println(owner+" 开户,初始金额为: "+balance);
	System.out.println("===========================");
	
}
	public void setBalance(double balance) {
		this.balance = balance;
	}

	public double getBalance() {
		return this.balance;
	}

	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("当前余额: " + this.balance + " ,当前状态:  " + this.state);
		System.out.println("===========================");
	}

	public void withdraw(double amount) {
		System.out.println(this.owner + " 取款  " + amount);
		state.withdraw(amount);
		System.out.println("当前余额: " + this.balance + " ,当前状态:  " + this.state);
		System.out.println("===========================");
	}


}

abstract class AccountState { // 账户状态父类
	protected Account account;

	public abstract void deposit(double amount);// 存款

	public abstract void withdraw(double amount);// 取款


	public abstract void stateCheck();   //账户状态检测和设置入口     一般通过boolean或数字int判断来设置状态       这里用int 
	//每次操作后要跟新状态变化
}

// 正常状态
class NormalState extends AccountState {
	public NormalState(Account account) { // 构造函数 形参为Account
		this.account = account;
	}

	public NormalState(AccountState state) { // 构造函数 形参为State
		this.account = state.account;
	}

	public void deposit(double amount) {
		account.setBalance(account.getBalance() + amount);
		stateCheck();//每一次存款、取款操作完成后    根据余额更新状态
	}

	public void withdraw(double amount) {
		account.setBalance(account.getBalance() - amount);
		stateCheck();//每一次存款、取款操作完成后    根据余额更新状态
	}

	public void computeInterest() {
		System.out.println("正常状态,无需利息");
	}

	public void stateCheck() { // 状态改变    每一次存款、取款操作完成后    根据余额更新状态
		if (account.getBalance() > -2000 && account.getBalance() <= 0) {
			account.setState(new OverdraftState(this));
		} else if (account.getBalance() == -2000) {
			account.setState(new RestrictedState(this));
		} else if (account.getBalance() < -2000) {
			System.out.println("操作受限");
		}
	}
	@Override
	public String toString() {
		
		return "正常状态";
	}

}

// 透支状态
class OverdraftState extends AccountState {
	public OverdraftState(AccountState state) {
		this.account = state.account;
	}

	@Override
	public void deposit(double amount) {
		account.setBalance(account.getBalance() + amount);
		stateCheck();//每一次存款、取款操作完成后    根据余额更新状态

	}

	@Override
	public void withdraw(double amount) {
		account.setBalance(account.getBalance() - amount);
		stateCheck();//每一次存款、取款操作完成后    根据余额更新状态

	}


	@Override
	public void stateCheck() {
		if (account.getBalance() > -2000 && account.getBalance() <= 0) {
			account.setState(new OverdraftState(this));

		} else if (account.getBalance() == -2000) {
			account.setState(new RestrictedState(this));
		} else if (account.getBalance() < -2000) {
			System.out.println("操作受限");
		}

	}
	
	@Override
	public String toString() {
		return "透支状态";
	}
}

// 受限状态
class RestrictedState extends AccountState {
	public RestrictedState(AccountState state) {
		this.account = account;
	}

	@Override
	public void deposit(double amount) {

		account.setBalance(account.getBalance() + amount);
		stateCheck();//每一次存款、取款操作完成后    根据余额更新状态
	}

	@Override
	public void withdraw(double amount) {
		System.out.println("操作受限,取款失败");//受限状态下无法取款
	}


	@Override
	public void stateCheck() {

		if (account.getBalance() > 0) {
			account.setState(new NormalState(this));

		} else if (account.getBalance() > -2000) {
			account.setState(new OverdraftState(this));
		}
	}
	
	@Override
	public String toString() {
		return "受限状态";
	}

}

输出2:

张三 开户,初始金额为: 0.0
===========================
张三 存款  1000.0
当前余额: 1000.0 ,当前状态:  正常状态
===========================
张三 取款  2000.0
当前余额: -1000.0 ,当前状态:  透支状态
===========================
张三 存款  3000.0
当前余额: 2000.0 ,当前状态:  透支状态
===========================
张三 取款  4000.0
当前余额: -2000.0 ,当前状态:  受限状态
===========================
张三 取款  1000.0
操作受限,取款失败
当前余额: -2000.0 ,当前状态:  受限状态
===========================

三、小结

状态模式:状态State是环境类Context的一个属性,代码1中Door类有Open和Close两种状态,代码2中Account类有正常状态、透支状态、受限状态三种状态,因为状态是环境类的一个属性,所有把State引用注入到Context类中,这是状态模式的关键。

State引用注入到Context类后,客户端就可以通过操作Context类对象来间接操作State类对象,很好的向客户端屏蔽了State类。

注意:至于Context引用是否需要注入到State类中,无关紧要,不是必须,本文两段代码为了操作方便,所有将Context引用注入到了State类中。

设计模式只重其意不重其形,学习每一中设计模式的时候,只要抓住它的最关键的点就好了,没有必要死记代码,代码为业务需求服务,设计模式也是如此。

 

附:状态模式与策略模式区别

1、类图、类的结构一样:

状态模式:Context环境类、State类(抽象状态类、具体状态类)

策略模式:Context环境类、Strategy类(抽象策略类、具体策略类)

两种模式都是行为型模式,UML图相同,都是将核心类(State类或Strategy类)注入到Context类中,在客户端通过操作Context环境类间接操作核心类(State类或Strategy类),巧妙的在客户端屏蔽核心类。

2、表达意义稍有不同:

状态可以看作是Context类的一个内在属性,是必不可少的,新建Context类对象时,Context类的初始化函数中就要初始化状态属性;

策略不是Context的属性,是Context类调用的一个外界的东西;

所以,一般核心类(State类或Strategy类)是内在属性的时候是状态模式,是外界东西的时候是策略模式。

3、代码逻辑稍有不同:状态模式是含有“状态切换”逻辑(最大的不同)

状态模式中一定含有“状态切换”逻辑,不管是在ConcreteState类中还是在Context类中,状态类中一定含有“状态切换”代码;

策略模式只是简单的在客户端切换策略,核心类(Strategy类)中没有“切换”逻辑。

其实,正是因为第二条,State是Context内在属性,所以有切换逻辑,Strategy是外在东西,所有没有切换逻辑。

所以,存在核心类(State类或Strategy类)切换逻辑的是状态模式,不存在的是策略模式。

 

状态模式:

https://blog.csdn.net/qq_36963950/article/details/102866284

策略模式:

https://blog.csdn.net/qq_36963950/article/details/102866291

 

 

上一篇:设计模式(十七)——备忘录模式

下一篇:设计模式(十九)——策略模式