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

mac2026-01-26  3

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

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

一、概述

官方解释: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

 

 

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

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

最新回复(0)