【设计模式系列19】状态模式原理分析及其和策略模式,责任链模式的区别
狀態(tài)模式原理分析
- 設(shè)計(jì)模式系列總覽
- 前言
- 什么是狀態(tài)模式
- 狀態(tài)模式示例
- 狀態(tài)模式角色
- 狀態(tài)模式與責(zé)任鏈模式
- 狀態(tài)模式與策略模式
- 狀態(tài)模式應(yīng)用場景
- 狀態(tài)模式優(yōu)缺點(diǎn)
- 總結(jié)
設(shè)計(jì)模式系列總覽
| 三大工廠模式 | 登機(jī)入口 |
| 策略模式 | 登機(jī)入口 |
| 委派模式 | 登機(jī)入口 |
| 模板方法模式 | 登機(jī)入口 |
| 觀察者模式 | 登機(jī)入口 |
| 單例模式 | 登機(jī)入口 |
| 原型模式 | 登機(jī)入口 |
| 代理模式 | 登機(jī)入口 |
| 裝飾者模式 | 登機(jī)入口 |
| 適配器模式 | 登機(jī)入口 |
| 建造者模式 | 登機(jī)入口 |
| 責(zé)任鏈模式 | 登機(jī)入口 |
| 享元模式 | 登機(jī)入口 |
| 組合模式 | 登機(jī)入口 |
| 門面模式 | 登機(jī)入口 |
| 橋接模式 | 登機(jī)入口 |
| 中介者模式 | 登機(jī)入口 |
| 迭代器模式 | 登機(jī)入口 |
| 狀態(tài)模式 | 登機(jī)入口 |
| 解釋器模式 | 登機(jī)入口 |
| 備忘錄模式 | 登機(jī)入口 |
| 命令模式 | 登機(jī)入口 |
| 訪問者模式 | 登機(jī)入口 |
| 軟件設(shè)計(jì)7大原則和設(shè)計(jì)模式總結(jié) | 登機(jī)入口 |
前言
狀態(tài)對(duì)于我們開發(fā)者而言是相當(dāng)熟悉的,平常開發(fā)中總是離不開對(duì)象的狀態(tài),比如我們審核流程,就是一個(gè)狀態(tài)不斷流轉(zhuǎn)的過程,訂單流程也是一個(gè)狀態(tài)不斷流轉(zhuǎn)的過程,而狀態(tài)模式就是為了更好地解決我們狀態(tài)流轉(zhuǎn)過程中的業(yè)務(wù)處理邏輯。
什么是狀態(tài)模式
狀態(tài)模式(State Pattern)也稱為狀態(tài)機(jī)模式(State Machine Pattern),是允許對(duì)象在內(nèi)部狀態(tài)發(fā)生改變的同時(shí)改變對(duì)象的行為,使得看起來像是修改了類一樣。
狀態(tài)模式中的類的行為是由狀態(tài)決定的,不同的狀態(tài)有不同的行為。狀態(tài)模式的意圖是讓一個(gè)對(duì)象在其內(nèi)部改變時(shí)行為也隨之一起改變。
狀態(tài)模式的核心就是給每一種狀態(tài)綁定一種行為。
好了,裝逼時(shí)刻又到了:Talk is cheap,Show you the code,先看一個(gè)非常簡單的例子。
狀態(tài)模式示例
下面我們就以訂單狀態(tài)的流轉(zhuǎn)來寫一個(gè)簡單的示例,我們假設(shè)訂單只有三個(gè)狀態(tài):待支付,待收貨,已收貨(完成)。
1、首先建立一個(gè)抽象的狀態(tài)類,這個(gè)類需要定義所有狀態(tài)的所有行為:
package com.zwx.design.pattern.state;public abstract class AbstractOrderState {protected OrderContext orderContext;public AbstractOrderState(OrderContext orderContext) {this.orderContext = orderContext;}public abstract void payOrder();public abstract void deliver();public abstract void receiveGoods(); }注意這里面集成了一個(gè)OrderContext對(duì)象,這個(gè)對(duì)象是用來負(fù)責(zé)狀態(tài)的切換的。
2、因?yàn)橛腥齻€(gè)狀態(tài),所以我們新建三個(gè)具體的狀態(tài)類來實(shí)現(xiàn)抽象狀態(tài)類:
- 待支付狀態(tài)類:
- 待發(fā)貨狀態(tài)類:
- 已收貨狀態(tài)類:
我們可以看到,每個(gè)狀態(tài)都綁定了一個(gè)行為(也可以支持綁定多個(gè)),并且在對(duì)應(yīng)的行為處理完畢之后會(huì)流轉(zhuǎn)到下一個(gè)狀態(tài),對(duì)于不屬于當(dāng)前狀態(tài)的行為則做出相應(yīng)的回應(yīng)。
3、再建立一個(gè)狀態(tài)上下文環(huán)境類,用來負(fù)責(zé)具體狀態(tài)的切換:
package com.zwx.design.pattern.state;/*** @author zwx* @version 1.0* @date 2020/10/5* @since jdk1.8*/ public class OrderContext {AbstractOrderState waitPaid;AbstractOrderState waitDeliver;AbstractOrderState receiveGoods;AbstractOrderState currState;//當(dāng)前狀態(tài)public OrderContext() {this.waitPaid = new WaitPaidOrderState(this);this.waitDeliver = new WaitDeliverOrderState(this);this.receiveGoods = new ReceiveGoodsOrderState(this);currState = waitPaid;}void setState(AbstractOrderState state){this.currState = state;}public void payOrder(){currState.payOrder();}public void deliver(){currState.deliver();}public void receiveGoods(){currState.receiveGoods();} }可以看到,這個(gè)類里面也有點(diǎn)委派模式的影子,不同的行為委派給對(duì)應(yīng)的對(duì)象進(jìn)行處理而自己不做處理,只負(fù)責(zé)狀態(tài)的切換。
4、最后再新建一個(gè)測試類進(jìn)行測試:
package com.zwx.design.pattern.state;public class TestState {public static void main(String[] args) {OrderContext orderContext = new OrderContext();orderContext.payOrder();orderContext.deliver();orderContext.receiveGoods();} }輸出結(jié)果為:
支付成功 商品已發(fā)貨并送達(dá)目的地 用戶已收到商品,此次交易結(jié)束狀態(tài)模式角色
從上面示例中,我們可以得出狀態(tài)模式主要有3個(gè)角色:
- 環(huán)境類角色(Context):定義客戶端需要的接口,內(nèi)部維護(hù)一個(gè)當(dāng)前狀態(tài)實(shí)例,并負(fù)責(zé)具體狀態(tài)的切換。
- 抽象狀態(tài)角色(State):定義每個(gè)狀態(tài)下對(duì)應(yīng)的行為,可以有一個(gè)或者多個(gè)行為。
- 具體狀態(tài)角色(ConcreteState):具體實(shí)現(xiàn)該狀態(tài)對(duì)應(yīng)的行為,并且在需要的情況下實(shí)現(xiàn)狀態(tài)的切換。
狀態(tài)模式與責(zé)任鏈模式
看這個(gè)狀態(tài)模式的實(shí)現(xiàn)是有點(diǎn)和責(zé)任鏈模式相似,都是一條鏈去處理,可以這么說在某種場景下這兩種模式可以互相替換,但是這兩種模式也是有本質(zhì)區(qū)別的。
- 狀態(tài)模式:
狀態(tài)模式的下一個(gè)節(jié)點(diǎn)是各個(gè)狀態(tài)對(duì)象已經(jīng)了解的,而且狀態(tài)的流轉(zhuǎn)就是由內(nèi)部進(jìn)行流轉(zhuǎn),客戶端無法決定。 - 責(zé)任鏈模式
“鏈路”上的對(duì)象并不知道下一個(gè)節(jié)點(diǎn)處理人是誰,而是由客戶端自行組裝決定的。
狀態(tài)模式與策略模式
狀態(tài)模式和策略模式都能用來消除大量的if/else場景,但是也有本質(zhì)區(qū)別。策略模式中各個(gè)策略之間是獨(dú)立的,相互可以替換的,任意選擇其中一個(gè)策略就能滿足需求,而且是由客戶端自己做出選擇。而狀態(tài)模式客戶端只能選擇初始節(jié)點(diǎn),后續(xù)就會(huì)自動(dòng)流轉(zhuǎn),各個(gè)狀態(tài)是一個(gè)整體,不存在可以互相替換的狀態(tài)。
狀態(tài)模式應(yīng)用場景
當(dāng)控制一個(gè)對(duì)象狀態(tài)的條件表達(dá)式過于復(fù)雜的時(shí)候,就可以考慮使用狀態(tài)模式,通過把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類中,這樣就可以把復(fù)雜的邏輯簡單化,使得對(duì)象的行為依賴于它的狀態(tài),并且會(huì)隨著狀態(tài)的改變而同時(shí)改變行為。
狀態(tài)模式主要應(yīng)用于以下場景:
- 1、對(duì)象的行為需要隨著狀態(tài)的改變而改變時(shí)。
- 2、當(dāng)我們一個(gè)操作中需要根據(jù)狀態(tài)來寫大量的if/else邏輯時(shí)
狀態(tài)模式優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 1、通過將每個(gè)狀態(tài)設(shè)置為獨(dú)立的對(duì)象,消除了代碼中存在的大量if/else等判斷分支,使得代碼更加簡潔,更容易維護(hù)。
- 2、將不同的狀態(tài)通過不同的類來表示,使得狀態(tài)切換時(shí)相比較于用數(shù)字或者字符串來表示時(shí)更加直觀,轉(zhuǎn)換目的也更加明確。
- 3、每個(gè)狀態(tài)類的職責(zé)單一明確,易于擴(kuò)展。
缺點(diǎn)
- 1、狀態(tài)過多會(huì)引起類膨脹(事實(shí)上這也是大部分設(shè)計(jì)模式的通病)。
- 2、狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)相對(duì)較為復(fù)雜,容易造成代碼混亂。
- 3、對(duì)于支持狀態(tài)切換的狀態(tài)類違反了開閉原則,因?yàn)橐坏顟B(tài)修改或者中間要新增狀態(tài),則需要修改對(duì)應(yīng)的源代碼,否則會(huì)出現(xiàn)狀態(tài)切換錯(cuò)誤。
總結(jié)
本文主要介紹了狀態(tài)模式的定義,并通過一個(gè)簡單的示例來實(shí)現(xiàn)了一個(gè)簡單的狀態(tài)模式,最后將狀態(tài)模式和責(zé)任鏈模式進(jìn)行了對(duì)比分析,明確了其和策略模式,責(zé)任鏈模式的區(qū)別。
請(qǐng)關(guān)注我,和孤狼一起學(xué)習(xí)進(jìn)步。
總結(jié)
以上是生活随笔為你收集整理的【设计模式系列19】状态模式原理分析及其和策略模式,责任链模式的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux icmp 时间戳过滤,ICM
- 下一篇: 秒懂设计模式之状态模式(State Pa