实际项目运用之State模式(状态模式)

1 模式简介 定义: 状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。这个模式将状态封装成独立的类,并将动作委托到代表当前状态的类的对象 状态模式的优点: >封装了转换规则 枚举可能的状态,在枚举状态之前需要确定状态种类 将所有与某个状态有关的行为放到一个类中,可方便增加新的状态 允许状态转换逻辑与状态对象合成一体,而非复杂条件语句块 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数 状态模式的缺点: >增加系统类和对象的个数 结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱 对”开闭原则”的支持不太好,增加新状态类需在状态类上增加行为方法 状态模式的适用场景: 1. 对象的行为依赖于它的状态,并且可以在运行时根据状态改变行为。 2. 代码中包含大量与对象状态有关的if/else语句 3. 接口幂等要求 状态模式和策略模式: 相同点是它们都需要根据需求选择相应的状态或策略 不同点是状态模式是在一个类中通过不同的动作切换不同的状态,而策略模式是为一个类选择某个策略,即状态模式中的Context是和多个状态关联的,而策略模式中的Context只和一个策略关联 状态模式角色介绍: (1)Context类,依赖倒置原则,通过适配器模式维护状态类 (2)State:抽象状态类或状态接口,用以抽象封装行为 (3)ConcreteState类:具体状态类,实现了State中的抽象方法 2 实际运用 借贷平台的订单,有审核-发布-抢单 等等 步骤,随着操作的不同,会改变订单的状态,通常通过if/else判断订单的状态,从而实现不同的逻辑,伪代码如下: if(审核){ //审核逻辑 }elseif(发布){ //发布逻辑 }elseif(接单){ //接单逻辑 } 上述解决方案缺点非常明显:这类代码难以应对变化,在添加一种状态时,我们需要手动添加if/else,在添加一种功能时,要对所有的状态进行判断。因此代码会变得越来越臃肿,并且一旦没有处理某个状态,便会发生极其严重的BUG,难以维护 2.1 状态模式应用 状态模式本质上是一种基于状态和事件的 状态机 ,下面是订单流程的状态图 通过状态图,我们再设计一张横纵坐标关系表来比较,图如下: 通过上述表 我们可以细化为一个二维数组,来表示状态与事件直接的关系: 2.2 代码实现 我们通过状态的各种图例分析来用代码实现逻辑 状态枚举类 public enum StateEnum { //订单生成 GENERATE(1, "GENERATE"), //已审核 REVIEWED(2, "REVIEWED"), //已发布 PUBLISHED(3, "PUBLISHED"), //待付款 NOT_PAY(4, "NOT_PAY"), //已付款 PAID(5, "PAID"), //已完结 FEED_BACKED(6, "FEED_BACKED"); private int key; private String value; StateEnum(int key, String value) { this.

实际项目运用之Responsibility-Chain模式(责任链模式)

1 模式概要 1.1 简介 责任链模式为请求创建一个接收者对象链,每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它会把请求传给下一个接收者,依此类推 责任链模式避免了请求的发送者和接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连成一条链,并且沿着这条链传递请求,直到有对象处理它为止 1.2 责任链模式优缺点 优点 >降低耦合度。它将请求的发送者和接收者解耦 简化了对象,使得对象不需要知道链的结构 增强给对象指派职责的灵活性,允许动态地新增或者删除责任链 增加新的请求处理类方便 缺点 >不能保证请求一定被接收; 系统性能将受到一定影响,调试时不方便,可能会造成循环调用 2 模式结构 2.1 对象定义 *Handler(抽象处理者)*: 定义一个处理请求的接口,提供对后续处理者的引用 *ConcreteHandler(具体处理者)*: 抽象处理者的子类,处理用户请求,可选将请求处理掉还是传给下家;在具体处理者中可以访问链中下一个对象,以便请求的转发 2.2 类图及设计 代码详解: 抽象处理者 public abstract class Handler { protected Handler nextHandler; // 下一个责任链成员 public Handler getNextHandler() { return nextHandler; } public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; } // 处理传递过来的时间 public abstract void handleMessage(int type); } 具体处理者 在当前处理者对象无法处理时,将执行权传给下一个处理者对象 :::java public class ConcreteHandler1 extends Handler { @Override public void handleMessage(int type) { if (type == 1 || type == 3) { System.

设计模式之Template模式(模版模式)

1 模式简介 1.1 模版方法模式的定义: 模版方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。 1.2 结构 1.3 模式的组成 抽象类(AbstractClass): 定义抽象的原语操作(primitive operation) ,具体的子类将重定义它们以实现一个算法, 实现一个模板方法,定义一个算法的骨架。该模板方法不仅调用原语操作,也调用定义。 具体子类 (ConcreteClass): 实现原语操作以完成算法中与特定子类相关的步骤。 1.4 优缺点 模版方法模式的优点:  封装不变部分,扩展可变部分;  提取公共代码,便于维护;  行为由父类控制,子类实现。 模版方法模式的缺点:  每一个不同的实现都需要一个子类来实现,导致类个数增加,使系统更加庞大 模版方法模式的适用场景:  当类中有多个子类共有的方法  当有重要的、复杂的方法时,可以考虑作为模板方法 2 案例 抽象类 @FunctionalInterface public interface MyPredicate<T> { boolean test(T t); /** *过滤用户 */ default List<Employee> filterEmployee(List<Employee> emps, MyPredicate<Employee> mp) { List<Employee> list = new ArrayList<>(); for (Employee employee : emps) { if (mp.

实际项目运用之Strategy模式(策略模式)

1. 策略模式概要 策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。 下面就以一个示意性的实现讲解策略模式实例的结构。  这个模式涉及到三个角色:  ● 环境(Context)角色:持有一个Strategy的引用。  ● 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。  ● 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。 1.1 案例代码 策略模式上下文 public class Context { //持有一个具体策略的对象 private Strategy strategy; /** * 构造函数,传入一个具体策略对象 * @param strategy 具体策略对象 */ public Context(Strategy strategy){ this.strategy = strategy; } /** * 策略方法 */ public void contextInterface(){ strategy.algorithmInterface(); } } 抽象策略类 public interface Strategy { /** * 策略方法 */ public void algorithmInterface(); } 具体策略类 public class ConcreteStrategyA implements Strategy { @Override public void algorithmInterface() { //相关的业务 } } public class ConcreteStrategyB implements Strategy { @Override public void algorithmInterface() { //相关的业务 } } public class ConcreteStrategyC implements Strategy { @Override public void algorithmInterface() { //相关的业务 } } 客户端