? 作者主页:欢迎来到我的技术博客😎
? 个人介绍:大家好,本人热衷于Java后端开发,欢迎来交流学习哦!( ̄▽ ̄)~*
🍊 如果文章对您有帮助,记得关注、点赞、收藏、评论??????
📣 您的支持将是我创作的动力,让我们一起加油进步吧!!!🎉🎉
状态模式(State Pattern)是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。该模式将对象的行为封装在不同的状态类中,使得在不同状态下可以选择不同的行为,从而使对象看起来好像修改了其类。
在引入状态模式之前,我们先来演示一下没有使用状态模式的业务场景。
业务:在一个车辆租赁应用中,车辆的状态有四种:可租用、已出租、维修中、已归还。现在要实现进行车辆状态之间状态的互相切换,每一种状态改变,都有可能要根据其他状态来更新处理。例如,如果车辆处于可租用状态,则可以执行出租、维修状态,如果车辆处于维修状态,则可以执行可出租、归还操作。
类图如下:
?
具体的类设计如下:
车辆租赁接口类:
public interface ICarRent {
//车辆的4种状态
public final static int AvailableState = 1; //可租用状态
public final static int RentedState = 2; //已出租状态
public final static int InServiceState = 3; //维修中状态
public final static int ReturnedState = 4; //已归还状态
//设置车辆的状态
public void setState(int state);
//车辆的动作
public void Available();
public void Rented();
public void InService();
public void Returned();
}
车辆租赁接口实现类:
public class CarRent implements ICarRent {
private int state;
@Override
public void setState(int state) {
this.state = state;
}
//执行可租用动作
@Override
public void Available() {
switch (this.state) {
case AvailableState :
System.out.println("车辆无法重复处于可租用状态");
break;
case RentedState :
System.out.println("车辆已出租");
this.setState(RentedState); //将车辆的状态由可租用变成已出租
break;
case InServiceState :
System.out.println("车辆处于维修中");
this.setState(InServiceState);
break;
case ReturnedState :
System.out.println("车辆无法处于已归还状态");
break;
}
}
//执行已出租动作
@Override
public void Rented() {
switch (this.state) {
case AvailableState :
System.out.println("车辆无法处于可租用状态");
break;
case RentedState :
System.out.println("车辆无法重复处于已租用状态");
break;
case InServiceState :
System.out.println("车辆处于维修中");
this.setState(InServiceState);
break;
case ReturnedState :
System.out.println("车辆已归还");
this.setState(ReturnedState);
break;
}
}
//执行维修中动作
@Override
public void InService() {
switch (this.state) {
case AvailableState :
System.out.println("车辆无法处于可租用状态");
break;
case RentedState :
System.out.println("车辆无法处于已租用状态");
break;
case InServiceState :
System.out.println("车辆无法处于重复处于维修状态");
break;
case ReturnedState :
System.out.println("车辆已归还");
this.setState(ReturnedState);
break;
}
}
//执行已归还动作
@Override
public void Returned() {
switch (this.state) {
case AvailableState :
System.out.println("车辆可租用");
this.setState(AvailableState);
break;
case RentedState :
System.out.println("车辆已出租");
this.setState(RentedState);
break;
case InServiceState :
System.out.println("车辆处于维修中");
this.setState(InServiceState);
break;
case ReturnedState :
System.out.println("车辆无法重复处于维修状态");
break;
}
}
}
客户端类:
public class client {
public static void main(String[] args) {
CarRent carRent = new CarRent();
carRent.setState(ICarRent.AvailableState);
carRent.Available();
carRent.Rented();
carRent.InService();
carRent.Returned();
}
}
通过上述代码,我们可以发现已经可以满足业务需求了,但是这种实现方式会存在下面的问题:
switch...case
这样的逻辑判断(if…else也是一样),使程序的可阅读性很差;因此,我们可以通过使用 状态模式 就可以很好地解决上述问题。
状态模式包含以下主要角色:
使用状态模式对上述案例进行改造,类图如下:
?
具体的类设计如下:
抽象状态类:
public abstract class CarState {
//声明环境角色类变量
protected Context context;
public void setContext(Context context) {
this.context = context;
}
//车辆可租用操作
public abstract void Available();
//车辆已出租操作
public abstract void Rented();
//车辆维修中操作
public abstract void InService();
//车辆已归还操作
public abstract void Returned();
}
车辆可租用状态类:
public class AvailableState extends CarState {
@Override
public void Available() {
System.out.println("车辆无法重复处于可租用状态");
}
@Override
public void Rented() {
System.out.println("车辆已出租");
super.context.setCarState(Context.RENTED_STATE);
super.context.Rented();
}
@Override
public void InService() {
System.out.println("车辆处于维修中");
super.context.setCarState(Context.IN_SERVICE_STATE);
super.context.InService();
}
@Override
public void Returned() {
System.out.println("车辆无法处于已归还状态");
}
}
车辆已出租状态类:
public class RentedState extends CarState {
@Override
public void Available() {
System.out.println("车辆无法处于可租用状态");
}
@Override
public void Rented() {
System.out.println("车辆无法重复处于已租用状态");
}
@Override
public void InService() {
System.out.println("车辆处于维修中");
super.context.setCarState(Context.IN_SERVICE_STATE);
super.context.InService();
}
@Override
public void Returned() {
System.out.println("车辆已归还");
super.context.setCarState(Context.RETURNED);
super.context.Returned();
}
}
车辆维修中状态类:
public class InServiceState extends CarState {
@Override
public void Available() {
System.out.println("车辆无法处于可租用状态");
}
@Override
public void Rented() {
System.out.println("车辆无法处于已租用状态");
}
@Override
public void InService() {
System.out.println("车辆无法处于重复处于维修状态");
}
@Override
public void Returned() {
System.out.println("车辆已归还");
super.context.setCarState(Context.RETURNED);
super.context.Returned();
}
}
车辆已归还状态类:
public class Returned extends CarState {
@Override
public void Available() {
System.out.println("车辆可租用");
super.context.setCarState(Context.AVAILABLE_STATE);
super.context.InService();
}
@Override
public void Rented() {
System.out.println("车辆已出租");
super.context.setCarState(Context.RENTED_STATE);
super.context.Rented();
}
@Override
public void InService() {
System.out.println("车辆处于维修中");
super.context.setCarState(Context.IN_SERVICE_STATE);
super.context.InService();
}
@Override
public void Returned() {
System.out.println("车辆无法重复处于维修状态");
}
}
环境类:
public class Context {
//定义对应状态对象的常量
public final static AvailableState AVAILABLE_STATE = new AvailableState();
public final static RentedState RENTED_STATE = new RentedState();
public final static InServiceState IN_SERVICE_STATE = new InServiceState();
public final static Returned RETURNED = new Returned();
//定义一个当前车辆状态变量
private CarState carState;
public CarState getCarState() {
return carState;
}
//设置当前状态对象
public void setCarState(CarState carState) {
this.carState = carState;
//设置当前状态对象中的Context对象
this.carState.setContext(this);
}
public void Available() {
this.Available();
}
public void Rented() {
this.Rented();
}
public void InService() {
this.InService();
}
public void Returned() {
this.Returned();
}
}
客户端类:
public class Client {
public static void main(String[] args) {
CarRent carRent = new CarRent();
carRent.setState(ICarRent.AvailableState);
carRent.Available();
carRent.Rented();
carRent.InService();
carRent.Returned();
}
}
测试结果:
?
优点:
缺点:
状态模式和策略模式的UML类图几乎一模一样,容易在初学时混淆。然而,它们有一些相似之处,但也存在着明显的区别。
状态模式(State Pattern):
策略模式(Strategy Pattern):
区别总结:
?
非常感谢您阅读到这里,如果这篇文章对您有帮助,希望能留下您的点赞👍 关注💖 分享👥 留言💬thanks!!!