定义:
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
结构:(书中图,侵删)
一个抽象的状态类,拥有一个与状态相关的行为方法
若干个具体的状态类
一个上下文类,持有抽象状态类
实例:
写到这里,看了一眼桌上的零食,想到了一个例子。
食品大概分为三个阶段,或者说三种状态:最佳食用期,可食用期(过了最佳食用期,但未过期),已过期。
食品类(包含:最佳食用天数、过期天数、出厂天数):
package designpattern.state;
public class Food {
private String name;
private int manufactureDays;
// 出厂天数
private int bestBeforeDays;
// 最佳食用天数(从出厂时间算起)
private int expiryDays;
// 保质期天数
private FoodState foodState;
public Food(String name,
int bestBeforeDays,
int expiryDays) {
this.name =
name;
this.bestBeforeDays =
bestBeforeDays;
this.expiryDays =
expiryDays;
this.foodState =
new BestBeforeState();
}
public void eat() {
foodState.reaction(this);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name =
name;
}
public int getManufactureDays() {
return manufactureDays;
}
public void setManufactureDays(
int manufactureDays) {
this.manufactureDays =
manufactureDays;
}
public int getBestBeforeDays() {
return bestBeforeDays;
}
public void setBestBeforeDays(
int bestBeforeDays) {
this.bestBeforeDays =
bestBeforeDays;
}
public int getExpiryDays() {
return expiryDays;
}
public void setExpiryDays(
int expiryDays) {
this.expiryDays =
expiryDays;
}
public FoodState getFoodState() {
return foodState;
}
public void setFoodState(FoodState foodState) {
this.foodState =
foodState;
}
}
抽象状态类:
package designpattern.state;
public interface FoodState {
public void reaction(Food food);
}
具体状态类:
最佳食用状态:
package designpattern.state;
public class BestBeforeState
implements FoodState {
@Override
public void reaction(Food food) {
if (food.getManufactureDays() <=
food.getBestBeforeDays()) {
System.out.print("第" + food.getManufactureDays() + "天吃,"
);
System.out.println("[" + food.getName() + "]在最佳食用期中,好吃~~"
);
} else {
food.setFoodState(new EatableState());
food.eat();
}
}
}
可食用状态:
package designpattern.state;
public class EatableState
implements FoodState {
@Override
public void reaction(Food food) {
if (food.getManufactureDays() <=
food.getExpiryDays()) {
System.out.print("第" + food.getManufactureDays() + "天吃,"
);
System.out.println("[" + food.getName() + "]在可食用期中,味道还可以"
);
} else {
food.setFoodState(new ExpiredState());
food.eat();
}
}
}
已过期状态:
package designpattern.state;
public class ExpiredState
implements FoodState {
@Override
public void reaction(Food food) {
if (food.getManufactureDays() >
food.getExpiryDays()) {
System.out.print("第" + food.getManufactureDays() + "天吃,"
);
System.out.println("[" + food.getName() + "]过期了,没法吃了"
);
} else {
food.setFoodState(new EatableState());
food.eat();
}
}
}
客户端:
package designpattern.state;
public class Client {
public static void main(String[] args) {
Food food =
new Food("面包", 1, 7);
// 设置最佳食用期1天,保质期7天
food.setManufactureDays(1
);
food.eat();
food.setManufactureDays(3
);
food.eat();
food.setManufactureDays(10
);
food.eat();
}
}
结果输出:
第1天吃,[面包]在最佳食用期中,好吃~~
第3天吃,[面包]在可食用期中,味道还可以
第10天吃,[面包]过期了,没法吃了
总结:
依旧是为了解耦的一个设计模式,通过抽象的方式来实现,感觉光看代码的话,很多设计模式其实长得都很像,本质区别只是在应用的场景上。
主要是理解在什么情况下应该用哪个设计模式。
而状态模式主要是用在,对象的行为依赖于它的状态,且状态间转换的条件判断相对比较复杂的情况,表现在代码中就是有很多条件判断分支。
从上面的例子,可以看出各个状态间的转换有一种传递的关系,而不是把所有其他的条件判断都写在里面,这样可以保证当前的状态只关注和自己相关的条件。