2020年已經進入倒計時了,大家立好的flag完成了嗎?2020實“鼠”不易,希望2021可以“牛”轉乾坤。
簡介
狀態模式是行爲型設計模式的一種。其設計理念是當對象的內部狀態發生改變時,隨之改變其行爲。狀態和行爲之間是一一對應的。
該模式主要用於,對象的行爲依賴於它的狀態,並且其行爲是隨着狀態的改變而切換時。
狀態模式UML類圖
類圖講解
State:抽象狀態接口(也可以定義成抽象類),該接口封裝了所有狀態所對應的行爲。
ConcreteStateA/B:具體狀態類,該類實現了抽象狀態接口,會根據自身對應的狀態來實現接口中定義的方法,還有另一個功能是指明如何過渡到下一個狀態。
Context:環境(上下文)角色,該類負責狀態的切換,還持有一個State實例,代表當前環境所處狀態。
案例講解
案例:通過狀態模式來實現自助售賣機的功能。
狀態接口
public interface State {
// 挑選商品
void choose();
// 付款
boolean payment();
// 分發商品
void dispenseCommodity();
}
挑選商品狀態類
public class ChooseGoods implements State {
VendingMachine machine;
public ChooseGoods(VendingMachine machine) {
this.machine = machine;
}
@Override
public void choose() {
if (machine.getCount() > 0) {
System.out.println("商品挑選成功,請及時付款!");
machine.setState(machine.getPaymentState());
} else {
System.out.println("很遺憾,商品售罄了!");
machine.setState(machine.getEmptyState());
}
}
@Override
public boolean payment() {
System.out.println("請先挑選商品!");
return false;
}
@Override
public void dispenseCommodity() {
System.out.println("請先挑選商品!");
}
}
付款狀態類
public class PaymentState implements State {
VendingMachine machine;
public PaymentState(VendingMachine machine) {
this.machine = machine;
}
@Override
public void choose() {
System.out.println("商品已選購完成請勿重複挑選");
}
@Override
public boolean payment() {
Random random = new Random();
int num = random.nextInt(10);
if(num % 2 == 0){
System.out.println("付款成功!");
machine.setState(machine.getDispenseCommodityState());
return true;
}
System.out.println("付款失敗,請重新支付!");
return false;
}
@Override
public void dispenseCommodity() {
System.out.println("請先完成支付!");
}
}
商品售罄狀態類
public class EmptyState implements State {
VendingMachine machine;
public EmptyState(VendingMachine machine) {
this.machine = machine;
}
@Override
public void choose() {
System.out.println("對不起商品已售罄!");
}
@Override
public boolean payment() {
System.out.println("對不起商品已售罄!");
return false;
}
@Override
public void dispenseCommodity() {
System.out.println("對不起商品已售罄!");
}
}
分發商品狀態類
public class DispenseCommodityState implements State {
VendingMachine machine;
public DispenseCommodityState(VendingMachine machine) {
this.machine = machine;
}
@Override
public void choose() {
System.out.println("請及時取走您的商品!");
}
@Override
public boolean payment() {
System.out.println("請及時取走您的商品!");
return false;
}
@Override
public void dispenseCommodity() {
System.out.println("請及時取走您的商品!");
machine.setState(machine.getChooseGoods());
}
}
自動售貨機 => Context角色
public class VendingMachine {
// 表示當前狀態
private State state = null;
// 商品數量
private int count = 0;
private State chooseGoods = new ChooseGoods(this);
private State paymentState = new PaymentState(this);
private State dispenseCommodityState = new DispenseCommodityState(this);
private State emptyState = new EmptyState(this);
public VendingMachine(int count) {
this.count = count;
this.state = this.getChooseGoods();
}
// 購買商品
public void purchase() {
// 挑選商品
state.choose();
// 支付成功
if (state.payment()) {
// 分發商品
state.dispenseCommodity();
}
}
// 獲取商品後將商品減一
public int getCount() {
return count--;
}
// get和set方法 ...
}
客戶端測試類
public class Client {
public static void main(String[] args) {
VendingMachine machine = new VendingMachine(1);
for (int i = 1; i < 4; i++) {
System.out.println("第" + i + "次購買。");
machine.purchase();
}
}
}
執行結果
總結
1、狀態模式將每個狀態所對應的行爲封裝到一個類中,大大提高了代碼的可讀性。並且通過這樣的設計還可以消除多餘的if-else語句,方便代碼的維護。
2、狀態模式符合“開閉原則”,容易增加和刪除狀態。
3、任何事情都有利弊,狀態模式也不例外。其最顯著的問題是,每個狀態都要對應一個類,當狀態過多時會產生大量的類,從而加大維護成本。
4、應用場景:當一個需求有很多狀態,並且狀態之間會進行轉換,不同狀態還對應不同的行爲時就可以考慮使用“狀態模式”。
今天的分享就到這裏了,如果感覺“菜鳥”寫的文章還不錯,記得點贊、轉發加關注呦!你們的支持就是我堅持下去的動力。文章哪裏寫的有問題的也希望大家可以指出,我會虛心受教。