行为型设计模式(二) 之 复杂条件封装来描述工作流变化常用状态模式

1 定义

状态模式(State Pattern)属于行为型设计模式,它主要是为了解决在当一个对象状态决定该对象的行为且该状态的条件表达式过于复杂时,把状态的判断逻辑进行单独封装为不同的状态,正如工作流中通过每个节点的状态来决定跳转下一个节点的流程。例如现实场景,我们工作中需要请假,在OA系统上走流程,假如请假天数是3天内是部门经理审批,然后是行政登记;如果5天内是先部门经理审批,接着是总监审批,最后是行政登记;如果10天内最终还要老板审批,最后行政登记,这里根据请假的天数决定了审批流程,其每个审批节点就是一个过程的状态。

2 实现

状态模式一般包含了3个角色,分别是:

  1. 环境上下文(Context):用来操作状态的上下文环境。例如上述定义举例的请假。
  2. 抽象状态(State):定义所有支持的状态的公共行为。例如上述定义举例的需要审批的人。
  3. 具体状态(ConcreteState):具体的状态实现,封装了具体的状态或行为。例如上述定义举例的审批者是经理或者行政。

环境类,内部定义了一个抽象状态对象,维护一个对状态对象的引用,用于定义当前的状态:

public class LeaveContext {
    private LeaveState mLeaveState;
    private int mDayCount;
    public LeaveContext(int dayCount) {
        mLeaveState = new ManagerState();
        mDayCount = dayCount;
        System.out.println("请假" + mDayCount + "天");
    }
    public void setLeaveState(LeaveState leaveState) {
        mLeaveState = leaveState;
    }
    public int getDayCount() {
        return mDayCount;
    }
    public void handle() {
        mLeaveState.handle(this);
    }
}

抽象状态类,它声明了审批人是谁和审批的动作方法:

public abstract class LeaveState {
    protected String mName;
    public LeaveState(String name) {
        mName = name;
    }
    public abstract void handle(LeaveContext context);
}

具体状态类,分别是经理、总监、老板和行政:

public class ManagerState extends LeaveState {
    public ManagerState() {
        super("经理审批状态");
    }
    @Override
    public void handle(LeaveContext context) {
        if (context.getDayCount() < 3) {
            System.out.println(mName + "同意");
            context.setLeaveState(new HRState());
        } else {
            System.out.println(mName + "同意,但还要请示上级");
            context.setLeaveState(new MajordomoState());
        }
        context.handle();
    }
}
public class MajordomoState extends LeaveState {
    public MajordomoState() {
        super("总监审批状态");
    }
    @Override
    public void handle(LeaveContext context) {
        if (context.getDayCount() < 5) {
            System.out.println(mName + "同意");
            context.setLeaveState(new HRState());
        } else {
            System.out.println(mName + "同意,但还要请示上级");
            context.setLeaveState(new BossState());
        }
        context.handle();
    }
}

public class BossState extends LeaveState {
    public BossState() {
        super("老板审批状态");
    }
    @Override
    public void handle(LeaveContext context) {
        System.out.println(mName + "同意");
        context.setLeaveState(new HRState());
        context.handle();
    }
}

public class HRState extends LeaveState {
    public HRState() {
        super("行政记录状态");
    }
    @Override
    public void handle(LeaveContext context) {
        System.out.println(mName + "同意");
        System.out.println("请假流程结束");
    }
}

客户端:

public class Main {
    public static void main(String[] args) {
        LeaveContext leaveContext = new LeaveContext(2);
        leaveContext.handle();

        LeaveContext leaveContext2 = new LeaveContext(4);
        leaveContext2.handle();

        LeaveContext leaveContext3 = new LeaveContext(5);
        leaveContext3.handle();
    }
}

输出结果:

请假2天
经理审批状态同意
行政记录状态同意
请假流程结束

请假4天
经理审批状态同意,但还要请示上级
总监审批状态同意
行政记录状态同意
请假流程结束

请假5天
经理审批状态同意,但还要请示上级
总监审批状态同意,但还要请示上级
老板审批状态同意
行政记录状态同意
请假流程结束

3 区别

3.1 与策略模式的区别

策略模式和状态模式都是行为型设计模式,他们在使用上非常相似,且实现都是3个角色,上下文、抽象和具体实现。区别在于:

  1. 策略模式是条件选择,但只会执行一次的选择。例如商场促销活动,我们只能选择一种方案进行结账。
  2. 状态模式也是条件选择,但会随着状态的改变而进行下一次选择。例如请假流程,根据工作完成状态和请假天数决定审批的流程。
  3. 如果两种模式要使用同一个例子的话,假如我们去旅游,策略模式是我们在出行前只需选择一种出行的方案直达目的地,可能是坐高铁或者坐飞机;而状态模式是我们先坐高铁到达景点A,然后再坐飞机到景点B。

3.2与责任链模式的区别

责任链模式和状态模式都是行为型设计模式,而且它们在使用上非常相似,我们来看看它们的区别:

  1. 状态模式为了解决状态的条件表过式过于复杂时的工作流,将每个节点进行逻辑封装和节点内决定下一节点的跳转,体现出工作流节点状态的变化
  2. 责任链模式用多个接收对象连成一个链为了处理发起的请求任务归属责任权限的问题,接收链由外部指定上下级关系,体现出接收对象权限的控制
  3. 如果两种模式要使用请假这个例子表达的话,状态模式更像是OA系统固定的请假流程,一个领导审批完后状态发生化变,然后自动转交到下一个领导去审批,而责任链模式更像是拿着请假条当面找领导签名,中间如果总监不在,甚至可以跳过他直接找老板签,发起者可以决定接收者。

4 总结

工作流节点状态变化的场景常可使用状态模式,因为对象是有状态的,而且对象的行为取决了它的状态,状态模式可以很好地消除复杂的条件分支语句,将各种状态转移逻辑分布到具体状态实现的子类之间,其优点在于将与特定状态相关的行为局部化,并且将不同状态的行为分割开来,减少相互间的依赖。当然缺点也是因为每个状态节点作为一个单独的类,这难免导致代码膨胀,同时因为结构与实现都较为复杂的原因也会容易导致程序结构和代码的混乱从而增加系统复杂度。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值