下面通过一个报销流程审批案例来说明状态模式的使用。
在状态模式中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所依赖于它的对象都得到通知并被自动更
新。
意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
何时使用:代码中包含大量与对象状态有关的条件语句。
如何解决:将各种具体的状态类抽象出来。
关键代码:通常命令模式的接口中只有一个方法。而状态模式的接口中有一个或者多个方法。而且,状态模式
的实现类的方法,一般返回值,或者是改变实例变量的值。也就是说,状态模式一般和对象的状态有关。实现
类的方法有不同的功能,覆盖接口中的方法。状态模式和命令模式一样,也可以用于消除 if…else 等条件选择
语句。
应用实例:1、打篮球的时候运动员可以有正常状态、不正常状态和超常状态。 2、曾侯乙编钟中,'钟是抽象
接口’,'钟A’等是具体状态,'曾侯乙编钟’是具体环境(Context)。
优点:1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状
态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、
允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个
状态对象,从而减少系统中对象的个数。
缺点:1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使
用不当将导致程序结构和代码的混乱。 3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态
模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类
的行为也需修改对应类的源代码。
使用场景:1、行为随状态改变而改变的场景。 2、条件、分支语句的代替者。
注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。
适用性:
一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
这个状态通常用一个或多个枚举常量表示。
通常,有多个操作包含这一相同的条件结构。
State模式将每一个条件分支放入一个独立的类中。
这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
假设我们有一个报销的流程: 员工提交报销申请 -> 直属部门领导审批 -> 财务审批 -> 结束。
package state
// ========== 状态机Context ==========
type Context struct {
State
}
// 更新审批状态
func (context *Context) SetState(state State) {
context.State = state
}
// 获取当前审批状态
func (context *Context) GetStateName() string {
return context.State.GetName()
}
// 同意审批
func (context *Context) Approval() {
context.State.Approval(context)
}
// 拒绝审批
func (context *Context) Reject() {
context.State.Reject(context)
}
package state
// ========== State状态==========
type State interface {
// 同意审批
Approval(context *Context)
// 拒绝审批
Reject(context *Context)
// 获取当前状态名称
GetName() string
}
package state
import "fmt"
// ========== EmployeeApproveState发起审批 ==========
type EmployeeApproveState struct{}
// Employee发起审批
func (employeeApproveState *EmployeeApproveState) Approval(context *Context) {
fmt.Println("员工发起审批!")
// 将状态指向直属领导审批
context.SetState(GetLeaderApproveState())
}
// Employee没有拒绝审批
func (employeeApproveState *EmployeeApproveState) Reject(context *Context) {
fmt.Println("员工审批被拒绝!")
}
func (employeeApproveState *EmployeeApproveState) GetName() string {
return "EmployeeApproveState"
}
func GetEmployeeApproveState() State {
return &EmployeeApproveState{}
}
package state
import "fmt"
// ========== leaderApproveState直属领导审批 ==========
type LeaderApproveState struct{}
// 直属领导审同意审批
func (leaderApproveState *LeaderApproveState) Approval(context *Context) {
fmt.Println("直属领导审批成功!")
// 将状态指向财务审批
context.SetState(GetFinanceApproveState())
}
// 直属领导拒绝审批
func (leaderApproveState *LeaderApproveState) Reject(context *Context) {
fmt.Println("直属领导拒绝审批!")
// 将状态指向员工
context.SetState(GetEmployeeApproveState())
}
func (leaderApproveState *LeaderApproveState) GetName() string {
return "LeaderApproveState"
}
func GetLeaderApproveState() State {
return &LeaderApproveState{}
}
package state
import "fmt"
// ========== FinanceApproveState财务审批 ==========
type FinanceApproveState struct{}
// 财务审批通过
func (financeApproveState *FinanceApproveState) Approval(context *Context) {
fmt.Println("财务审批成功!")
fmt.Println("出发打款操作!")
context.SetState(GetEndApproveState())
}
// 财务拒绝审批
func (financeApproveState *FinanceApproveState) Reject(context *Context) {
fmt.Println("财务拒绝审批!")
context.SetState(GetLeaderApproveState())
}
func (financeApproveState *FinanceApproveState) GetName() string {
return "FinanceApproveState"
}
func GetFinanceApproveState() State {
return &FinanceApproveState{}
}
package state
import "fmt"
// ========== EndApproveState审批结束 ==========
type EndApproveState struct{}
// 审批结束
func (endApproveState *EndApproveState) Approval(context *Context) {
fmt.Println("审批结束!")
}
// 拒绝审批
func (endApproveState *EndApproveState) Reject(context *Context) {
fmt.Println("审批结束!")
}
func (endApproveState *EndApproveState) GetName() string {
return "FinanceApproveState"
}
func GetEndApproveState() State {
return &EndApproveState{}
}
package main
import (
"fmt"
. "proj/state"
)
func main() {
context := Context{}
context.State = GetEmployeeApproveState()
// 员工发起审批
fmt.Println("current state: ", context.GetStateName())
context.Approval()
// 直属领导审批
fmt.Println("current state: ", context.GetStateName())
context.Approval()
// 财务审批
fmt.Println("current state: ", context.GetStateName())
context.Approval()
// 结束审批
fmt.Println("current state: ", context.GetStateName())
context.Approval()
}
# 输出
current state: EmployeeApproveState
员工发起审批!
current state: LeaderApproveState
直属领导审批成功!
current state: FinanceApproveState
财务审批成功!
出发打款操作!
current state: FinanceApproveState
审批结束!
package main
import (
"fmt"
. "proj/state"
)
func main() {
context := Context{}
context.State = GetEmployeeApproveState()
// 员工发起审批
fmt.Println("current state: ", context.GetStateName())
context.Approval()
// 直属领导审批
fmt.Println("current state: ", context.GetStateName())
context.Reject()
// 员工重新发起审批
fmt.Println("current state: ", context.GetStateName())
context.Approval()
// 直属领导审批
fmt.Println("current state: ", context.GetStateName())
context.Approval()
}
# 输出
current state: EmployeeApproveState
员工发起审批!
current state: LeaderApproveState
直属领导拒绝审批!
current state: EmployeeApproveState
员工发起审批!
current state: LeaderApproveState
直属领导审批成功!
package com.state;
// ========== 状态机Context ==========
public class Context {
private State state;
// 更新审批状态
public void setState(State state) {
this.state = state;
}
// 获取当前审批状态
public String getStateName() {
return this.state.getName();
}
// 同意审批
public void approval() {
this.state.approval(this);
}
// 拒绝审批
public void reject() {
this.state.reject(this);
}
}
package com.state;
// ========== State状态==========
public interface State {
// 同意审批
void approval(Context context);
// 拒绝审批
void reject(Context context);
// 获取当前状态名称
String getName();
}
package com.state;
// ========== EmployeeApproveState发起审批 ==========
public class EmployeeApproveState implements State{
// Employee发起审批
@Override
public void approval(Context context) {
System.out.println("员工发起审批!");
// 将状态指向直属领导审批
context.setState(LeaderApproveState.getLeaderApproveState());
}
// Employee没有拒绝审批
@Override
public void reject(Context context) {
System.out.println("员工审批被拒绝!");
}
@Override
public String getName() {
return "EmployeeApproveState";
}
public static State getEmployeeApproveState() {
return new EmployeeApproveState();
}
}
package com.state;
// ========== leaderApproveState直属领导审批 ==========
public class LeaderApproveState implements State{
// 直属领导审同意审批
@Override
public void approval(Context context) {
System.out.println("直属领导审批成功!");
// 将状态指向财务审批
context.setState(FinanceApproveState.getFinanceApproveState());
}
// 直属领导拒绝审批
@Override
public void reject(Context context) {
System.out.println("直属领导拒绝审批!");
// 将状态指向员工
context.setState(EmployeeApproveState.getEmployeeApproveState());
}
@Override
public String getName() {
return "LeaderApproveState";
}
public static State getLeaderApproveState() {
return new LeaderApproveState();
}
}
package com.state;
// ========== FinanceApproveState财务审批 ==========
public class FinanceApproveState implements State{
// 财务审批通过
@Override
public void approval(Context context) {
System.out.println("财务审批成功!");
System.out.println("出发打款操作!");
context.setState(EndApproveState.getEndApproveState());
}
// 财务拒绝审批
@Override
public void reject(Context context) {
System.out.println("财务拒绝审批!");
context.setState(LeaderApproveState.getLeaderApproveState());
}
@Override
public String getName() {
return "FinanceApproveState";
}
public static State getFinanceApproveState() {
return new FinanceApproveState();
}
}
package com.state;
// ========== EndApproveState审批结束 ==========
public class EndApproveState implements State{
// 审批结束
@Override
public void approval(Context context) {
System.out.println("审批结束!");
}
// 拒绝审批
@Override
public void reject(Context context) {
System.out.println("审批结束!");
}
@Override
public String getName() {
return "FinanceApproveState";
}
public static State getEndApproveState() {
return new EndApproveState();
}
}
package com.state;
public class Test {
public static void main(String[] args) {
Context context = new Context();
context.setState(EmployeeApproveState.getEmployeeApproveState());
// 员工发起审批
System.out.println("current state: " + context.getStateName());
context.approval();
// 直属领导审批
System.out.println("current state: " + context.getStateName());
context.approval();
// 财务审批
System.out.println("current state: "+ context.getStateName());
context.approval();
// 结束审批
System.out.println("current state: " + context.getStateName());
context.approval();
}
}
# 程序输出
current state: EmployeeApproveState
员工发起审批!
current state: LeaderApproveState
直属领导审批成功!
current state: FinanceApproveState
财务审批成功!
出发打款操作!
current state: FinanceApproveState
审批结束!
package com.state;
public class Test1 {
public static void main(String[] args) {
Context context = new Context();
context.setState(EmployeeApproveState.getEmployeeApproveState());
// 员工发起审批
System.out.println("current state: " + context.getStateName());
context.approval();
// 直属领导审批
System.out.println("current state: " + context.getStateName());
context.reject();
// 员工重新发起审批
System.out.println("current state: "+ context.getStateName());
context.approval();
// 直属领导审批
System.out.println("current state: " + context.getStateName());
context.approval();
}
}
# 程序输出
current state: EmployeeApproveState
员工发起审批!
current state: LeaderApproveState
直属领导拒绝审批!
current state: EmployeeApproveState
员工发起审批!
current state: LeaderApproveState
直属领导审批成功!