声明: 本文
内容属于《Head First 设计模式》阅读笔记
,文中涉及到的知识案例参考该书并发善编写。《Head First 设计模式》
通过有趣的图表+文字的形式,让人自然学习设计模式,非常棒
,推荐阅读
。
允许对象在内部状态改变时改变它的行为,对象看起来就像修改了它的类。即:当一个对象的状态发生变化时,该对象所有与状态相关的方法的逻辑都会发生相应变化,(因为变化太大,所以)给人的感觉就像是换了一个对象(类实例)一样。
首先,将所有状态下的所有相关方法抽取到一个State总接口中,然后有多少个状态就创建多少个State实现,每个State实现需要根据自己的状态,对那些(该状态下支持的)方法进行业务逻辑编写,对(该状态下不支持的)方法进行不支持提示(或抛出异常)。 然后,当某个对象有状态的需求时。就可以使这个对象持有所有的State实现(即:持有所有可能的状态)。同时这个对象再设置一个currentState字段,用来指向当前所处的状态(即:指向当前对应的State实现)。当需要切换状态时,就改变currentState的指向。 最后,在这个对象需要调用到状态相关的方法时,直接使用currentState,而不直接使用对应的State实现。由于currentState是灵活指向不同的State实现的,所以当这个对象的状态发生变化时,currentState指向也会发生变化,那么即便调用的是同样的方法,也会走不同的逻辑(即:状态发生变化时,委派对象也发生了变化)。这样一来,对象在内部状态改变时就能改变它的行为,这个对象看起来就像修改了它的类一样,发生了翻天覆地的变化。
简单的,在购买商品时,该商品会有对应的订单状态信息,如下图所示:
BillState
:
/**
* 订单状态
*
* @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @date 2020/4/6 14:47:36
*/
public interface BillState {
/**
* 状态名
*
* return 状态名
*/
String name();
/**
* (买家)购物
*/
default void shopping() {
throw new UnsupportedOperationException("状态【" + this.getClass().getSimpleName() + "】下, 不支持sopping操作");
}
/**
* (商家)发货
*/
default void shipping() {
throw new UnsupportedOperationException("状态【" + this.getClass().getSimpleName() + "】下, 不支持shipping操作");
}
/**
* (收寄中心)揽件
*/
default void packaging() {
throw new UnsupportedOperationException("状态【" + this.getClass().getSimpleName() + "】下, 不支持packaging操作");
}
/**
* (物流)开始运输
*/
default void transport() {
throw new UnsupportedOperationException("状态【" + this.getClass().getSimpleName() + "】下, 不支持transport操作");
}
/**
* (快递小哥)派送
*/
default void dispatch() {
throw new UnsupportedOperationException("状态【" + this.getClass().getSimpleName() + "】下, 不支持dispatch操作");
}
/**
* (买家)签收 or 拒签
*
* @param accept
* true - 买家签收;
* false - 买家拒签
*/
default void signAccept(boolean accept) {
throw new UnsupportedOperationException("状态【" + this.getClass().getSimpleName() + "】下, 不支持signAccept操作");
}
}
DispatchState
:
import com.szlaozicl.designpattern.status.GoodsLogisticsInfo;
import com.szlaozicl.designpattern.status.status.BillState;
import lombok.RequiredArgsConstructor;
/**
* 派送状态
* <p>
* 注: 在派送状态下,唯一能做的就是 => 等待买家签收或拒签
*
* @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @date 2020/4/6 15:46:03
*/
@RequiredArgsConstructor
public class DispatchState implements BillState {
private final GoodsLogisticsInfo goodsLogisticsInfo;
@Override
public String name() {
return "派送状态";
}
@Override
public void signAccept(boolean accept) {
if (accept) {
System.out.println("(买家签收, 交易完成。进入)已收货状态");
// 将状态置为 已收货状态
goodsLogisticsInfo.setCurrentBillState(goodsLogisticsInfo.getHasReceiptedState());
} else {
System.out.println("(买家拒签, 交易完成。进入)已退货状态");
// 将状态置为 已退货状态
goodsLogisticsInfo.setCurrentBillState(goodsLogisticsInfo.getHasReturnedState());
}
}
}
StartingState
:
import com.szlaozicl.designpattern.status.GoodsLogisticsInfo;
import com.szlaozicl.designpattern.status.status.BillState;
import lombok.RequiredArgsConstructor;
/**
* 起始状态
*
* 注: 在起始状态下,唯一能做的就是 => 买
*
* @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @date 2020/4/6 15:46:03
*/
@RequiredArgsConstructor
public class StartingState implements BillState {
private final GoodsLogisticsInfo goodsLogisticsInfo;
@Override
public String name() {
return "起始状态";
}
@Override
public void shopping() {
System.out.println("(买家)购物");
// 将状态置为 已购物状态
goodsLogisticsInfo.setCurrentBillState(goodsLogisticsInfo.getHasShoppedState());
}
}
GoodsLogisticsInfo
:
import com.szlaozicl.designpattern.status.status.BillState;
import com.szlaozicl.designpattern.status.status.impl.*;
import lombok.Data;
/**
* 商品物流信息
*
* @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @date 2020/4/6 14:47:04
*/
@Data
public class GoodsLogisticsInfo {
/** 所有可能的状态 */
private BillState startingState;
private BillState hasShoppedState;
private BillState hasShippedState;
private BillState hasPackagedState;
private BillState transportState;
private BillState dispatchState;
private BillState hasReceiptedState;
private BillState hasReturnedState;
/** 当前状态 */
private BillState currentBillState;
public GoodsLogisticsInfo() {
this.startingState = new StartingState(this);
this.hasShoppedState = new HasShoppedState(this);
this.hasShippedState = new HasShippedState(this);
this.hasPackagedState = new HasPackagedState(this);
this.transportState = new TransportState(this);
this.dispatchState = new DispatchState(this);
this.hasReceiptedState = new HasReceiptedState();
this.hasReturnedState = new HasReturnedState();
this.currentBillState = this.startingState;
}
public void currStateInfo() {
System.err.println("订单当前处于【" + currentBillState.name() + "】");
}
public void shopping() {
currentBillState.shopping();
}
public void shipping() {
currentBillState.shipping();
}
public void packaging() {
currentBillState.packaging();
}
public void transport() {
currentBillState.transport();
}
public void dispatch() {
currentBillState.dispatch();
}
public void signAccept(boolean accept) {
currentBillState.signAccept(accept);
}
}
/**
* 状态模式 --- 测试
*
* @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
* @date 2020/4/6 9:33:50
*/
public class Test {
public static void main(String[] args) {
GoodsLogisticsInfo gli = new GoodsLogisticsInfo();
// 测试 - 做当前状态下能做的事
gli.currStateInfo();
gli.shopping();
gli.currStateInfo();
gli.shipping();
gli.currStateInfo();
gli.packaging();
gli.currStateInfo();
gli.transport();
gli.currStateInfo();
gli.dispatch();
gli.currStateInfo();
gli.signAccept(true);
gli.currStateInfo();
// 测试 - 做当前状态下不能做的事
gli.signAccept(false);
}
}
运行测试类main方法,控制台输出:
状态模式学习完毕 !
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。