状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化.
一个复杂的业务中可能存在大量的 if else等逻辑条件判断,对于后期维护来说是非常危险和复杂的。而状态模式也是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来.
状态模式可以消除大量的条件分支语句,内部通过状态转移,来减少之间的相互依赖
比如为某网盘会员产品开发,有以下常见场景:
会员等级 | 权限 |
---|---|
普通用户 | 存储照片、文件 |
会员 | 极速下载、5T空间… |
超级会员 | 小视频自动备份、音视频倍速播放… |
权限获取类
package design.pattern;
import java.util.ArrayList;
public class UserRule {
/**
* 等级 1普通用户 2会员 3超级会员
*/
private Integer level = 1;
/**
* 权限容器
*/
private ArrayList<String> ruleList = new ArrayList<String>() {
{
add("上传文件");
add("下载文件");
}
};
public UserRule(Integer level) {
this.level = level;
}
/**
* 获取权限列表
*
* @return
*/
public ArrayList<String> getRuleList() {
if (this.level == 2) { //会员
//todo 权限获取
ruleList.add("极速下载");
ruleList.add("5T空间");
} else if (this.level == 3) { //超级会员
//todo 权限获取
ruleList.add("光速下载");
ruleList.add("10T空间");
ruleList.add("小视频自动备份");
ruleList.add("音视频倍速播放");
}
return ruleList;
}
}
客户端调用:
Integer requestLevel = 3;
UserRule userRule = new UserRule(requestLevel);
ArrayList<String> ruleList = userRule.getRuleList();
//打印权限
System.out.println("会员等级" + requestLevel + "权限列表:");
for (Object object : ruleList) {
System.out.println(object);
}
output:
会员等级3权限列表:
上传文件
下载文件
光速下载
10T空间
小视频自动备份
音视频倍速播放
似乎看起来我们的代码足够简单,很好的满足了根据等级返回权限的需求
我们重点关注下获取权限列表的根据不同的条件分支,处理不同的todo 的业务逻辑,如果我们加入了更多的等级,更复杂的权限计算方式等等功能, 这个if else将会更加的庞大起来.
就在这时产品过来又给你提了个v2.0的需求.
我们发现如果再加上返回下个版本的权限,真的是够了,再过几天不一定又出什么需求,这个方法看起来都要崩溃了. 看来需要优化一下了。
首先我们建立一个抽象类(核心作用方便子类约束和传递)
State.java
package design.pattern.Rules;
import design.pattern.UserRule;
import design.pattern.UserVo;
import java.util.ArrayList;
public abstract class State {
/**
* 用户对象
*/
protected UserRule userRule;
/**
* 权限容器
*/
protected ArrayList<String> ruleList = new ArrayList<String>() {
{
add("上传文件");
add("下载文件");
}
};
public State(UserRule userRule) {
this.userRule = userRule;
}
public abstract ArrayList<String> getRuleList(UserVo userVo);
}
继承State.java状态类,实现各自的会员返回类
package design.pattern.Rules;
import design.pattern.UserRule;
import design.pattern.UserVo;
import java.util.ArrayList;
/**
* 一类会员
*/
public class MemberOne extends State {
public MemberOne(UserRule userRule) {
super(userRule);
}
/**
* 获取权限列表
*
* @return
*/
public ArrayList<String> getRuleList(UserVo userVo) {
//如果是一类会员(普通)
if (userVo.getLevel() == 1) {
return ruleList;
} else {
userRule.setState(new MemberTwo(userRule)); //设置下一级别类
return userRule.getRuleList(userVo); //获取下一个级别的详情
}
}
}
剩下的两个会员类
package design.pattern.Rules;
import design.pattern.UserRule;
import design.pattern.UserVo;
import java.util.ArrayList;
/**
* 三类会员
*/
public class MemberTwo extends State {
public MemberTwo(UserRule userRule) {
super(userRule);
}
/**
* 获取权限列表
*
* @return
*/
public ArrayList<String> getRuleList(UserVo userVo) {
if (userVo.getLevel() == 2) {
ruleList.add("极速下载");
ruleList.add("5T空间");
return ruleList;
}else{
userRule.setState(new MemberThree(userRule));
return userRule.getRuleList(userVo);
}
}
}
package design.pattern.Rules;
import design.pattern.UserRule;
import design.pattern.UserVo;
import java.util.ArrayList;
/**
* 三类会员
*/
public class MemberThree extends State {
public MemberThree(UserRule userRule) {
super(userRule);
}
/**
* 获取权限列表
*
* @return
*/
public ArrayList<String> getRuleList(UserVo userVo) {
//最高级
ruleList.add("光速下载");
ruleList.add("10T空间");
ruleList.add("小视频自动备份");
ruleList.add("音视频倍速播放");
return ruleList;
}
}
为了参数方便传递管理,我们在下面单独声明一个view object类.
UserRule.java (桥梁类)
package design.pattern;
import design.pattern.Rules.MemberOne;
import design.pattern.Rules.State;
import java.util.ArrayList;
public class UserRule {
/**
* 具体权限对象
*/
private State currentRule;
public UserRule() {
currentRule = new MemberOne(this);
}
/**
* 设置权限对象
*
* @param state
*/
public void setState(State state) {
this.currentRule = state;
}
public ArrayList<String> getRuleList(UserVo userVo) {
return this.currentRule.getRuleList(userVo);
}
}
userRule类为我们优化前充满了条件判断的类,对他进行了解耦合.可以理解为对内调用类,对外暴露类的桥梁类 userVo对象是我们的参数对象,这里主要用于等级判断. 如果不成立,则进行重新设置下一个处理规则类,并同样调用规则列表方法。
UserVo.java (参数类)
package design.pattern;
public class UserVo {
private String name;
private Integer level;
public UserVo(String name, Integer level) {
this.name = name;
this.level = level;
}
public String getName() {
return name;
}
public Integer getLevel() {
return level;
}
public void setName(String name) {
this.name = name;
}
public void setLevel(int level) {
this.level = level;
}
}
客户端调用:
UserVo userVo = new UserVo("小红", 1);
UserRule userRule = new UserRule();
ArrayList<String> ruleList = userRule.getRuleList(userVo);
//打印
System.out.println("用户" + userVo.getName() + "当前权限如下:");
for (Object object : ruleList) {
System.out.println(object);
}
//他的下个权限可以获得
userVo.setLevel(userVo.getLevel() + 1);
ruleList = userRule.getRuleList(userVo);
System.out.println("用户" + userVo.getName() + "将要权限如下:");
for (Object object : ruleList) {
System.out.println(object);
}
output:
用户小红当前权限如下:
上传文件
下载文件
用户小红将要权限如下:
上传文件
下载文件
极速下载
5T空间
if (userVo.getLevel() == 1) {
return ruleList;
} else {
userRule.setState(new MemberTwo(userRule)); //设置下一级别类
return userRule.getRuleList(userVo); //获取下一个级别的详情
}
思考这段代码存在的问题? 如何优化?
策略模式与状态模式极其相似,但是二者有其内在的差别
userRule.setState(new MemberTwo(userRule));),