
一、行为型模式在面向对象的世界里如何优雅地组织对象间的交互、分配职责是每一位开发者都会反复思考的问题。直接硬编码交互逻辑固然简单但当业务复杂度上升、对象协作关系变得错综复杂时这种方式就会让代码变得僵化、难以扩展。行为型设计模式正是为了解决这一痛点而诞生的一套思想体系。它们关注如何定义对象之间的通信方式和职责分配通过命令、迭代、观察者、策略等手段让对象间的协作更具灵活性、可复用性和可维护性。在 Java 开发中行为型模式主要包含以下 11 种经典实现模板方法模式 (Template Method)定义一个操作中的算法的骨架而将一些步骤延迟到子类中使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。Java 设计模式・模板方法模式篇从思想到代码实现-CSDN博客策略模式 (Strategy)定义一系列的算法把它们一个个封装起来并且使它们可相互替换让算法独立于使用它的客户而变化。Java 设计模式・策略模式篇从思想到代码实现-CSDN博客命令模式 (Command)将一个请求封装为一个对象从而使你可以用不同的请求对客户进行参数化支持可撤销操作。Java 设计模式・命令模式篇从思想到代码实现-CSDN博客责任链模式 (Chain of Responsibility)将请求的发送者和接收者解耦使多个对象都有机会处理这个请求形成一条处理链。Java 设计模式・责任链模式篇从思想到代码实现-CSDN博客状态模式 (State)允许一个对象在其内部状态改变时改变它的行为对象看起来似乎修改了它的类。观察者模式 (Observer)定义对象间的一种一对多的依赖关系当一个对象的状态发生改变时所有依赖它的对象都得到通知并被自动更新。Java 设计模式・观察者模式篇从思想到代码实现-CSDN博客中介者模式 (Mediator)用一个中介对象来封装一系列的对象交互使各对象不需要显式地相互引用从而降低耦合。Java 设计模式・中介者模式篇从思想到代码实现-CSDN博客迭代器模式 (Iterator)提供一种方法顺序访问一个聚合对象中的各个元素而又不暴露其内部的表示。访问者模式 (Visitor)表示一个作用于某对象结构中的各元素的操作它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。备忘录模式 (Memento)在不破坏封装性的前提下捕获一个对象的内部状态并在该对象之外保存这个状态以便以后恢复。解释器模式 (Interpreter)给定一个语言定义它的文法的一种表示并定义一个解释器这个解释器使用该表示来解释语言中的句子。二、状态模式2.1 定义允许一个对象在其内部状态改变时改变它的行为看起来就像这个对象修改了它的类一样。可以把状态模式想象成一个对象比如 “订单”有多种状态待支付、已支付、已发货、已完成每个状态对应一套独立的行为比如 “待支付” 状态下只能执行 “支付” 操作不能执行 “确认收货”当对象的状态切换时它的行为会自动跟着切换而不需要用大量的if/else或switch来判断状态。2.2 角色环境Context角色也称为上下文它定义了客户程序需要的接口维护一个当前状态并将与状态相关的操作委托给当前状态对象来处理。抽象状态State角色定义一个接口用以封装环境对象中的特定状态所对应的行为。具体状态Concrete State角色实现抽象状态所对应的行为。三、代码实现经典实现为了方便理解本文类名采用中文3.1 抽象状态角色public interface 灯状态 { // 开灯操作 void on(灯 light); // 关灯操作 void off(灯 light); // 故障操作 void breakDown(灯 light); // 获取当前状态名称 String getName(); }3.2 环境角色public class 灯 { private 灯状态 statu; // 初始化为关闭状态 public 灯() { statu new 关闭状态(); System.out.println(灯初始化完成当前状态 statu.getName()); } // 供具体状态类调用设置状态 public void setStatu(灯状态 statu) { this.statu statu; } // 对外暴露的行为委托给当前状态 public void on() { statu.on(this); } public void off() { statu.off(this); } public void breakDown() { statu.breakDown(this); } public String getStatu() { return statu.getName(); } }3.3 具体状态角色public class 打开状态 implements 灯状态{ Override public void on(灯 light) { System.out.println(已打开无需重复开灯); } Override public void off(灯 light) { System.out.println(打开状态 → 关闭状态合法); light.setStatu(new 关闭状态()); } Override public void breakDown(灯 light) { System.out.println(打开状态 → 故障状态合法); light.setStatu(new 故障状态()); } Override public String getName() { return 打开; } }public class 关闭状态 implements 灯状态 { Override public void on(灯 light) { System.out.println(关闭状态 → 打开状态合法); // 状态转换逻辑封装在具体状态中 light.setStatu(new 打开状态()); } Override public void off(灯 light) { System.out.println(已关闭无需重复关灯); } Override public void breakDown(灯 light) { System.out.println(关闭状态 → 故障状态合法); light.setStatu(new 故障状态()); } Override public String getName() { return 关闭; } }public class 故障状态 implements 灯状态{ Override public void on(灯 light) { System.out.println(故障状态禁止开灯); } Override public void off(灯 light) { System.out.println(故障状态 → 关闭状态维修后复位); light.setStatu(new 关闭状态()); } Override public void breakDown(灯 light) { System.out.println(已故障无需重复标记故障); } Override public String getName() { return 故障; } }3.4 客户端public class 客户端 { public static void main(String[] args) { 灯 light new 灯(); light.on(); light.breakDown(); light.off(); light.breakDown(); light.on(); } }灯初始化完成当前状态关闭 关闭状态 → 打开状态合法 打开状态 → 故障状态合法 故障状态 → 关闭状态维修后复位 关闭状态 → 故障状态合法 故障状态禁止开灯 Process finished with exit code 0四、代码实现共享状态结合享元模式这里使用了享元模式可以看我的这一篇博客了解一下Java 设计模式・享元模式篇从思想到代码实现-CSDN博客4.1 抽象状态角色public interface 灯状态 { // 开灯操作 void on(); // 关灯操作 void off(); // 故障操作 void breakDown(); // 获取当前状态名称 String getName(); }4.2 环境角色ublic class 灯 { private static 灯状态 curStatu; public static final 灯状态 onInstance new 打开状态(); public static final 灯状态 offInstance new 关闭状态(); public static final 灯状态 breakDowmInstance new 故障状态(); // 初始化为关闭状态 public 灯() { curStatu offInstance; System.out.println(初始化完成当前状态 curStatu.getName()); } // 供具体状态类调用设置状态 public static void setCurStatu(灯状态 statu) { curStatu statu; } public void on() { curStatu.on(); } public void off() { curStatu.off(); } public void breakDown() { curStatu.breakDown(); } public static String getCurStatu() { return curStatu.getName(); } }4.3 具体状态角色public class 打开状态 implements 灯状态{ Override public void on() { System.out.println(已打开无需重复开灯); } Override public void off() { System.out.println(打开状态 → 关闭状态合法); 灯.setCurStatu(灯.offInstance); } Override public void breakDown() { System.out.println(打开状态 → 故障状态合法); 灯.setCurStatu(灯.breakDowmInstance); } Override public String getName() { return 打开; } }public class 关闭状态 implements 灯状态 { Override public void on() { System.out.println(关闭状态 → 打开状态合法); 灯.setCurStatu(灯.onInstance); } Override public void off() { System.out.println(已关闭无需重复关灯); } Override public void breakDown() { System.out.println(关闭状态 → 故障状态合法); 灯.setCurStatu(灯.breakDowmInstance); } Override public String getName() { return 关闭; } }public class 故障状态 implements 灯状态{ Override public void on() { System.out.println(故障状态禁止开灯); } Override public void off() { System.out.println(故障状态 → 关闭状态维修后复位); 灯.setCurStatu(灯.offInstance); } Override public void breakDown() { System.out.println(已故障无需重复标记故障); } Override public String getName() { return 故障; } }4.4 客户端public class 客户端 { public static void main(String[] args) { 灯 light1 new 灯(); 灯 light2 new 灯(); light1.on(); light2.breakDown(); light1.on(); light2.off(); } }初始化完成当前状态关闭 初始化完成当前状态关闭 关闭状态 → 打开状态合法 打开状态 → 故障状态合法 故障状态禁止开灯 故障状态 → 关闭状态维修后复位五、代码实现环境类实现状态转换5.1 抽象状态角色public interface 灯状态 { void display(); // 获取当前状态名称 String getName(); }5.2 环境角色public class 灯 { private 灯状态 curStatu; private 打开状态 openStatu; private 关闭状态 closeStatu; // 初始化为关闭状态 public 灯() { openStatu new 打开状态(); closeStatu new 关闭状态(); curStatu closeStatu; System.out.println(初始化完成当前状态 curStatu.getName()); } // 供具体状态类调用设置状态 public void setCurStatu(灯状态 statu) { this.curStatu statu; } public void click(){ if (curStatu openStatu){ this.setCurStatu(closeStatu); this.curStatu.display(); } else { this.setCurStatu(openStatu); this.curStatu.display(); } } }5.3 具体抽象角色public class 打开状态 implements 灯状态{ Override public void display() { System.out.println(灯是打开状态); } Override public String getName() { return 打开; } }public class 关闭状态 implements 灯状态 { Override public void display() { System.out.println(灯是关闭状态); } Override public String getName() { return 关闭; } }5.4 客户端public class 客户端 { public static void main(String[] args) { 灯 light new 灯(); light.click(); light.click(); } }初始化完成当前状态关闭 灯是打开状态 灯是关闭状态 Process finished with exit code 0六、优缺点6.1 优点消除大量冗余的条件判断 状态模式将每个状态的行为封装到独立类中上下文如订单只需调用当前状态的方法无需判断状态代码更简洁。状态行为与状态切换逻辑解耦上下文类只负责维护当前状态不关心状态如何切换、行为如何执行符合单一职责原则。状态切换逻辑更清晰、易维护状态的切换规则集中在具体状态类中而非散落在业务代码的各个角落扩展性极强新增状态时只需新增一个实现状态接口的类无需修改现有代码6.2 缺点类数量膨胀 每个状态对应一个独立的类如果对象的状态非常多比如有 10 种状态会创建大量的状态类增加代码的管理成本状态切换逻辑分散调试成本略高如果状态流转逻辑复杂比如有分支调试时需要跳转到多个类中查看不如if/else直观。不适用于状态极少的场景如果对象只有 2-3 种简单状态比如开关只有 “开 / 关”用状态模式会 “过度设计”反而不如if/else简洁。七、适用场景7.1 适用场景对象有多个状态且不同状态对应不同行为代码中存在大量与状态相关的if/else或switch且经常修改状态切换规则复杂且需要灵活扩展7.2 不适用场景对象只有极少数状态如 2 种且状态切换逻辑简单比如开关的开 / 关状态几乎不会变更且行为固定比如一个对象的状态在创建后就不再改变项目追求极简代码量且状态相关逻辑极少修改过度设计反而增加成本。八、对比学习8.1 策略模式对比学习Java 设计模式・策略模式篇从思想到代码实现-CSDN博客二者都基于 “封装变化” 的思想代码结构几乎一致但设计意图和使用场景完全不同。维度状态模式策略模式设计意图处理「状态驱动的行为变化」对象的行为随内部状态自动切换处理「算法 / 策略的灵活替换」外部选择不同策略完成同一类任务切换方式状态由对象内部自动切换比如待支付→已支付策略由外部客户端手动指定比如用户选支付宝 / 微信支付状态 / 策略关系状态之间有依赖 / 流转关系比如已支付只能切已发货策略之间相互独立支付宝和微信支付无依赖核心关键词状态、流转、自动切换策略、选择、手动替换8.2 责任链模式对比学习二者都能处理 “多分支逻辑”但核心目标不同常用来对比 “不同分支逻辑的处理方式”。维度状态模式责任链模式核心目标处理「同一对象的不同状态」行为随状态变处理「请求的多节点处理」请求沿链传递直到被处理逻辑触发基于对象内部状态自动触发基于请求内容由链上节点判断是否处理核心特征状态闭环有明确的状态流转链式传递节点无闭环单向传递8.3 if/else/switch 硬编码对比学习这是 “优雅实现” 和 “基础实现” 的对比也是状态模式的核心替代场景。维度状态模式if/else/switch 硬编码代码结构状态封装为独立类无冗余判断大量嵌套判断代码臃肿扩展性新增状态只需加类符合开闭原则新增状态需修改原有判断代码易出错维护性状态行为集中在对应类易调试判断逻辑散落在一处修改易影响其他分支适用场景状态多、需扩展、需维护状态极少2-3 种、逻辑简单九、其他相关设计模式Java 设计模式・总结目录篇从思想到代码实现-CSDN博客