版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35165632/article/details/84063341
状态模式 :
允许对象在内部状态改变时,改变他的行为,对象看起来好像是修改了他的类。
解释:状态模式允许一个对象基于内部状态而拥有不同的行为。和程序状态机不同,状态模式用类代表状态。Context会将内容委托给当前状态对象。通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了。状态模式和策略模式有相同的类图,但是他们的意图不同。策略模式通常会用行为或算法配置context类,状态转换state是由context控制的。使用状态模式通常会导致设计类中的类数目增加。状态类可以被多个context实例共享。
状态模式样例演示:蹭一波双11热度,来说订单。
/**
抛开电商不说,但从一个寒酸的小商城的订单系统来说,
他们的设计特别的繁琐,通过一系列复杂的状态来控制订单的行为
以及客户的行为。
**/
public class Loan{
// 待付款
final static int DaiFuKuan = 0;
// 待发货
final static int DaiFaHuo = 2;
// 已发货
final static int YiFaHuo = 3;
// 已收货
final static int YiShouHuo = 4;
// 交易完成
final static int JiaoYiWanCheng = 5;
// 订单状态
private int loanState;
public Loan(){
// 默认订单创建了状态为待付款
loanState = DaiFuKuan;
}
// 付款
public void fuKuan(){
if(DaiFuKuan==state){
System.out.println("付款成功!");
}else if(DaiFaHuo==state){
System.out.println("已经付款过,无需再次付款!");
}else if(YiFaHuo ==state){
System.out.println("已经发货,无需再次付款!");
}else if(YiShouHuo==state){
System.out.println("已经收货,无需再次付款!");
}else{
System.out.println("交易完成,无需再次付款!");
}
}
// 催促卖家发货
public void faHuo(){
if(DaiFuKuan==state){
System.out.println("您现在还未付款,无法督促卖家发货!");
}else if(DaiFaHuo==state){
System.out.println("催促发货成功!");
}else if(YiFaHuo ==state){
System.out.println("已经发货,无需催促!");
}else if(YiShouHuo==state){
System.out.println("已经收货,无需催促!");
}else{
System.out.println("交易完成,无需催促!");
}
}
// 收货
public void shouHuo(){
if(DaiFuKuan==state){
System.out.println("您现在还未付款,无法收货!");
}else if(DaiFaHuo==state){
System.out.println("货物未到达无法收货!");
}else if(YiFaHuo ==state){
System.out.println("货物未到达无法收货!");
}else if(YiShouHuo==state){
System.out.println("收货成功!");
}else{
System.out.println("交易完成,无法再次收货!");
}
}
}
就这样看似完美严谨的一个订单就被设计好了,但是,如果现在需要增加退款的请求呢???当然我们依然可以严谨的把退款的逻辑写的很好,但是呢?为什么我们不选择一个捷径呢,那么我们就来看下面的设计。
public class LoanContext{
// 待付款状态
private LoanState daiFuKuanState;
// 待发货状态
private LoanState daiFaHuoState;
// 已发货状态
private LoanState yiFaHuoState;
// 已收货状态
private LoanState yiShouHuoState;
// 交易完成状态
private LoanState jiaoYiWanChengState;
// 已退款状态
private LoanState yiTuiKuanState;
// 当前订单状态
private LoanState state;
public LoanContext(){
// 把本对象的引用交给状态
daiFuKuanState = new DaiFuKuanState(this);
daiFaHuoState = new DaiFaHuoState(this);
yiFaHuoState = new YiFaHuoState(this);
yiShouHuoState = new YiShouHuoState(this);
jiaoYiWanChengState = new JiaoYiWanChengState(this);
yiTuiKuanState = new YiTuiKuanState(this);
// 默认状态为 待付款
state = daiFuKuanState;
}
// 收货
public void shouHuo(){
state.shouHuo();
}
// 发货
public void faHuo(){
state.fahuo();
}
// 付款
public void fuKuan(){
state.fuKuan();
}
// 退货
public void tuiHuo(){
state.tuiHuo();
}
}
这样订单的处理类就完成了,然后整理下各个订单的信息
// 订单状态抽象类
public Abstract class LoanState{
private LoanContext context;
public LoanState (LoanContext context){
this.context = context;
}
public void shouHuo();
public void faHuo();
public void fuKuan();
public void tuiHuo();
}
/**
待付款状态
**/
public class DaiFuKuanState extends LoanState{
// 收货
public void shouHuo(){
System.out.println("您未付款,无法收货");
}
// 付款
public void fuKuan(){
System.out.println("付款成功!");
// 设置状态为待发货。
context.setState(context.getDaiFaHuo());
}
// 发货
public void faHuo(){
System.out.println("您未付款,无法发货!");
}
// 收货
public void shouHuo(){
System.out.println("您未付款,无法收货!");
}
// 退款
public void tuiKuan(){
System.out.println("您未付款,无法退款!");
}
}
/**
待发货状态
**/
public class DaiFaHuoState extends LoanState{
// 收货
public void shouHuo(){
System.out.println("货未发出无法收货,无法收货");
}
// 付款
public void fuKuan(){
System.out.println("已经付款,无法二次付款!");
}
// 发货
public void faHuo(){
System.out.println("催促发货成功!卖家已发货!");
context.setState(context.yiFaHuo());
}
// 收货
public void shouHuo(){
System.out.println("货物未到!");
}
// 退款
public void tuiKuan(){
System.out.println("货物已发无法退款!");
}
}
按照这种方式继续对其他类进行修改之后,一个完整的订单系统就完成了。通过context控制了订单的状态直接进行了下一步。而且增加了拓展性和可维护性!