狀態模式
- 允許一個對象在其內部狀態改變時改變它的行爲,這個對象看起來似乎修改了它的類。
- 狀態模式主要解決的是當控制一個對象狀態轉換的條件表達式過於複雜時的情況。把狀態的判斷邏輯轉移到表系不同狀態的一系列類當中,可以把複雜的邏輯簡化。
- 每個人、事務在不同的狀態下會有不同表現動作,而一個狀態又會在不同的表現下轉移到寫一個不同的狀態。
- 在State模式中我們將狀態邏輯和動作實現進行分離。當一個操作中要維護大量的分支語句,並且這些分支依賴於對象的狀態。State模式將每一個分支都封裝到獨立的類中。
State模式結構
優點
- 將與特定狀態相關的行爲局部化,並且將不同狀態的行爲分割開來。
- 消除龐大的條件分支語句,把各種狀態轉移邏輯分佈到State的子類之間,減少了相互間的依賴。
- 顯式化進行狀態轉換:爲不同的狀態引入獨立的對象,使得狀態的轉換變得更如明確。而且狀態對象可以保證上下文不會發生內部狀態不一致的狀況,因爲上下文中只有一個變量來記錄狀態對象,只要爲這一個變量賦值就可以了。
缺點
State模式問題主要是邏輯分散化,狀態邏輯分佈到了很多的State的子類中,很難看到整個的狀態邏輯圖,這也帶來了代碼的維護問題。
本質
- 根據狀態來分離和選擇行爲
- 狀態模式是狀態驅動,由上下文負責。
State模式和Strategy模式簡單對比
- State模式和Strategy模式有很大程度上的相似:它們都有-一個Context類,都是通過委託(組合)給一個具有多個派生類的多態基類實現Context的算法邏輯。
- 兩者最大的差別就是State模式中派生類持有指向Context對象的引用,並通過這個引用調用Context中的方法,但在Strategy模式中就沒有這種情況。
實現
public abstract class State {
public abstract void Handle(Context context);
}
public class ConcreteStateA extends State{
@Override
public void Handle(Context context) {
context.setState(new ConcreteStateB()); //設置A的下一個狀態是B
}
}
class ConcreteStateB extends State{
@Override
public void Handle(Context context) {
context.setState(new ConcreteStateC()); //設置B的下一個狀態是C
}
}
class ConcreteStateC extends State{
@Override
public void Handle(Context context) {
context.setState(new ConcreteStateA()); //設置C的下一個狀態是A
}
}
public class Context {
State state;
public Context(State state) { //定義Context的初始狀態
super();
this.state = state;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
System.out.println("當前狀態爲"+state);
}
public void request(){
state.Handle(this); //對請求做處理並且指向下一個狀態
}
}
實例
【問題】
工作流中的請假流程:
- 某人提出請假申請,先由項目經理審批,如果項目經理不同意,審批就直接結束。
- 如項目經理同意,再看是否超過3天,如果三天以內,審批直接結束。
- 否則,交給部門經理,部門絡理審覈後,無論是否同意,審批直接結束。
package 狀態模式;
public class Context {
private State st;
private int days;
private String name;
private String pro;
private String dept;
private boolean ProjectManager,DepartmentManager,BossManager;
public Context(int days, String name, String pro, String dept, boolean projectManager, boolean departmentManager,
boolean boss) {
super();
this.days = days;
this.name = name;
this.pro = pro;
this.dept = dept;
ProjectManager = projectManager;
DepartmentManager = departmentManager;
this.BossManager = boss;
}
public boolean isBossManager() {
return BossManager;
}
public void setBossManager(boolean bossManager) {
BossManager = bossManager;
}
public Context( int days, String name, String pro, String dept, boolean projectManager,
boolean departmentManager) {
super();
this.days = days;
this.name = name;
this.pro = pro;
this.dept = dept;
ProjectManager = projectManager;
DepartmentManager = departmentManager;
}
public Context() {
super();
// TODO Auto-generated constructor stub
}
public int getDays() {
return days;
}
public void setDays(int days) {
this.days = days;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isProjectManager() {
return ProjectManager;
}
public void setProjectManager(boolean projectManager) {
ProjectManager = projectManager;
}
public boolean isDepartmentManager() {
return DepartmentManager;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
public String getPro() {
return pro;
}
public void setPro(String pro) {
this.pro = pro;
}
public void setDepartmentManager(boolean departmentManager) {
DepartmentManager = departmentManager;
}
public void leave() {
st.leave(this);
}
}
package 狀態模式;
public abstract class State {
public abstract void leave(Context con);
}
package 狀態模式;
public class Accept extends State {
@Override
public void leave(Context con) {
if(con.isProjectManager()==false) {
System.out.println(con.getPro()+"經理不同意請假!"+con.getName()+"的請假");
}else {
Less3 tdl=new Less3();
tdl.leave(con);
}
}
}
package 狀態模式;
public class Less3 extends State {
@Override
public void leave(Context con) {
if(con.getDays()<=3) {
System.out.println(con.getPro() +"項目經理同意!"+con.getName()+"的請假審批通過!共請假"+con.getDays()+"天!");
}else {
System.out.println("請假時間超過三天,請移至"+con.getDept()+"部門經理處!");
More3_Less7 tdo=new More3_Less7();
tdo.leave(con);
}
}
}
package 狀態模式;
public class More3_Less7 extends State {
@Override
public void leave(Context con) {
if(con.getDays()<=7) {
System.out.println(con.getDept()+"部門經理同意!"+con.getName()+"的請假審批通過!共請假"+con.getDays()+"天!");
}else {
System.out.println("請假時間超過7天,請移至總經理!");
More7 tdo=new More7();
tdo.leave(con);
}
}
}
package 狀態模式;
public class More7 extends State {
@Override
public void leave(Context con) {
if(con.isBossManager()==true) {
System.out.println(con.getPro()+"項目經理同意!"+con.getDept()+"部門經理同意!總經理同意!"+con.getName()+"的請假審批通過!共請假"+con.getDays()+"天!");
}else {
System.out.println(con.getPro()+"項目經理同意!"+con.getDept()+"部門經理同意!總經理不同意!"+con.getName()+"的請假審批不通過!");
}
}
}
package 狀態模式;
public class Client {
public static void main(String[] args) {
Context con = new Context(8,"菜雞","設計模式","設計",true,true,true);
con.setName("菜雞");
con.setPro("設計模式");
con.setDept("設計");
con.setDays(8);
con.setProjectManager(true);
con.setDepartmentManager(true);
con.leave();
}
}