状态模式,我是这么理解的:用多态实现替换多重if嵌套
它和策略模式看起来很像,都可以消除if else,但是策略模式针对点在于算法,而状态模式针对点在于状态的切换
demo:宾馆对房间的操作
首先,假设他有这么几种状态:空闲、预订、入住
有这么几种操作:预订、取消预定、入住、退房
针对这种有多个状态且互相之间有操作的情景就可以使用状态模式,消除大量if else
接下来:No code No BB
1>状态接口:State
public interface State {
String getStateDescription();//显示状态
void Book(Room room);//预定
void checkin(Room room);//入住
void unBook(Room room);//取消预定
void checkout(Room room);//退房
}
2>状态实现类:FreeState
@Slf4j
public class FreeState implements State {
@Override
public String getStateDescription() {
return "当前为空闲状态";
}
@Override
public void Book(Room room) {
//进行预定操作。。。。。。
//状态便成为已预定状态
room.setState(new BookState());
}
@Override
public void checkin(Room room) {
//进行入住操作
//状态变更为已入住
room.setState(new CheckinState());
}
@Override
public void unBook(Room room) {
//空闲状态无法执行--取消预定操作
log.info("空闲状态无法取消预定");
}
@Override
public void checkout(Room room) {
//空闲状态无法进行退房操作
log.info("空闲状态无法退房");
}
}
BookState:
@Slf4j
public class BookState implements State {
@Override
public String getStateDescription() {
return"当前为预定状态";
}
@Override
public void Book(Room room) {
log.info("当前已经为预定状态");
}
@Override
public void checkin(Room room) {
room.setState(new CheckinState());
}
@Override
public void unBook(Room room) {
room.setState(new FreeState());
}
@Override
public void checkout(Room room) {
log.info("预定状态无法退房");
}
}
CheckInState:
@Slf4j
public class CheckinState implements State {
@Override
public String getStateDescription() {
return "当前状态为入住状态";
}
@Override
public void Book(Room room) {
log.info("入住状态无法预定");
}
@Override
public void checkin(Room room) {
log.info("已入住状态无法入住");
}
@Override
public void unBook(Room room) {
log.info("已入住状态无法取消预定");
}
@Override
public void checkout(Room room) {
room.setState(new FreeState());
}
}
3>需要一个包含状态的实体,状态必须是指某个东西的状态,不然没有存在的意义
Room:
@Data
@Slf4j
public class Room {
private State state;
private String roomNum;
/**
* 功能描述: 预定
*/
public void bookRoom() {
state.Book(this);
}
/**
* 功能描述: 取消预定
*/
public void unBookRoom() {
state.unBook(this);
}
/**
* 功能描述: 入住
*/
public void checkinRoom() {
state.checkin(this);
}
/**
* 功能描述: 退房
*/
public void checkoutRoom() {
state.checkout(this);
}
/**
* 功能描述: 房间状态
*/
public void showRoomState() {
log.info(roomNum+state.getStateDescription());
}
}
4>接下来测试类可以看出设计模式让代码简洁了很多:假设我们要预订一间空闲的房间
public class Test {
public static void main(String[] args) {
//状态模式适用于有多种状态,并且每种状态都有几种操作可以选择
//FreeState,BookState,CheckinState其实都相当于一个一级条件的判断,里面的每个方法其实相当于一个二级判断
//一般会有两个状态作比较,一个是当前状态(可以从数据库查询)
//一个是要更改的状态
//不使用设计模式--多重if条件判断
String currentState = "free";//当前状态
String wantState = "Book";//想要更改的状态
if(currentState.equals("free")) {//空闲状态
if(wantState.equals("free")) {
System.out.println("已经是空闲状态");
}else if(wantState.equals("Book")) {
currentState = "Book";
}else if (wantState.equals("checkin")) {
currentState = "checkin";
}else {
System.out.println("空闲状态无法更改为退房状态");
}
}else if(currentState.equals("Book")) {//预定状态
}else {//入住状态
}
//使用设计模式---代码精简很多
Room room = new Room();
room.setRoomNum("9521");
room.setState(new FreeState());
room.bookRoom();
}
}
代码说明一切!!!
ps:这里强调两点
1>实际撸代码中,都是从数据库查询当前状态,但是我们数据库中状态可能是1,2,3,4,这样的,而我们怎么把它转换为状态的具体实现类呢?这就需要在包含状态的实体类中做判断,然后new相应的实体状态类,调用方法(其实我觉得不应该是这样,这样还是会有if判断,但是暂时没有想到好的办法让状态对应上状态的具体实现类)
2>具体的状态实现类需要实现接口的所有方法,有的可能压根就不需要判断,这时可以考虑写一个抽象状态类,然后抽象实体类继承,抽象状态类可以给默认实现,这样具体的实现类就只需要重写需要的方法即可