状态模式
定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。也就是说封装逻辑。
从图上看,跟上一节讲的策略模式几乎一样。策略模式侧重不同的策略的唯一选定,一旦选定某个策略就不应该换成另一个策略。而状态模式是定制一系列状态,根据判断逻辑取决某个状态。策略模式相当去旅游选择的交通工具,要么火车要么飞机要么其他,只能有一种最适当的策略。状态模式能够有多种状态变化,比如火车卖票,卖票的状态分为售罄和售卖。
代码示例
抽象状态类
public interface TicketState {
void sell(int ticketNum, TicketOffice office);
}
首先定义公共接口,同时传参买票处,供给状态内部调用其他状态。
环境类
public class TicketOffice {
private TicketState ticketState = new SaleInState();
private int ticketNum;
public TicketOffice(int ticketNum){
this.ticketNum = ticketNum;
}
public void sell() {
ticketState.sell(--ticketNum, this);
}
public void setState(TicketState state) {
ticketState = state;
}
}
各具体状态类
//售卖状态
public class SaleInState implements TicketState {
public void sell(int ticketNum, TicketOffice office) {
if (ticketNum == 0) {
office.setState(new SelloutState());//当票卖完了,状态切换为售罄状态
} else {
System.out.println("还剩下" + ticketNum + "张票");
}
}
}
//售罄状态
public class SelloutState implements TicketState {
public void sell(int ticketNum, TicketOffice office) {
System.out.println("卖光了");
}
}
客户端
TicketOffice office = new TicketOffice(10);//放入10张票
for (int i = 0; i < 12; i++) {
office.sell();//模拟有12个人买票
}
输出为
还剩下9张票
还剩下8张票
还剩下7张票
还剩下6张票
还剩下5张票
还剩下4张票
还剩下3张票
还剩下2张票
还剩下1张票
卖光了
卖光了
从代码可以看出,状态模式与策略模式有明显的区别,策略模式在外部选择一个最适当的策略,而状态模式在内部有多种切换,环境类和客户端不需要知道有哪些状态。要注意的是,状态之间必须有联系,不然就失去意义。有些人会说,这不是if..else..语句就搞定了吗,确实如此,但是突然新增一个状态就要多加一条else..if,要判断这又要判断那,一不小心bug就产生。状态庞大时,if..else..就显得力不从心。而状态模式,可以简化复杂度,以扩展的形式应变需求。不好的是,需要知道各种状态,而且状态一多,类就随之多起来。不足之处望指教。