策略模式与责任链模式学习笔记:从入门到理解

策略模式与责任链模式学习笔记:从入门到理解

你好!作为一名 Java Web 后端开发工程师,初学设计模式时对不同模式感到困惑是很正常的。策略模式(Strategy Pattern)和责任链模式(Chain of Responsibility Pattern)都是行为型设计模式,它们在某些方面有相似之处,但也存在显著的区别。这篇笔记将帮助你从头梳理这两种设计模式,并通过生活中的例子和代码示例,让你更清晰地理解它们以及何时选择使用。

一、策略模式 (Strategy Pattern)

1. 什么是策略模式?

想象一下,你在计划一次出行,从家到公司,你可以选择多种交通方式:挤公交、坐地铁、打出租车或者骑共享单车。每种方式都是一种策略,具体选择哪种策略取决于当时的情况(比如时间、天气、预算等)。

策略模式的定义:它定义了算法家族,分别封装起来,让它们之间可以互相替换。此模式让算法的变化独立于使用算法的客户。

简单来说,策略模式就是将这些不同的"出行方式"(算法)封装成独立的类,让你可以动态地选择使用哪一种。

2. 生活中的例子

  • 支付方式:在电商网站购物,结账时可以选择支付宝支付、微信支付、银行卡支付、花呗分期等,每一种支付方式就是一种策略。
  • 文件压缩:压缩软件可以使用不同的压缩算法,如 ZIP、RAR、7Z,用户可以选择其中一种策略进行压缩。
  • 排序算法:对一个数据集进行排序,可以选择冒泡排序、快速排序、归并排序等,每种排序算法也是一种策略。
  • 导航软件的路线规划:导航软件会提供多种路线策略,如"时间最短"、"路程最短"、"避开高速"等。

3. 策略模式的结构

策略模式主要包含以下三个角色:

  • Context (上下文环境):它持有一个对策略对象的引用,并最终调用策略对象的方法。它不关心具体的策略是什么,只负责在运行时接收或设置一个具体的策略,然后将请求委托给当前选中的策略。
  • Strategy (抽象策略):这是一个接口或抽象类,定义了所有支持的算法的公共接口。Context 使用这个接口来调用某个具体策略定义的算法。
  • ConcreteStrategy (具体策略):实现了 Strategy 接口,封装了具体的算法或行为。每个具体策略类代表一种算法实现。

(用文字描述结构关键点)

  • 你会有一个 Strategy 接口,里面定义了一个方法,比如 executeAlgorithm()
  • 然后有很多个实现了 Strategy 接口的 ConcreteStrategyA, ConcreteStrategyB 类,它们各自实现了 executeAlgorithm() 方法,代表不同的算法。
  • 最后有一个 Context 类,它内部维护一个 Strategy 类型的成员变量。Context 类有一个方法可以让客户端设置具体使用哪个 ConcreteStrategy,还有一个方法会调用当前 Strategy 对象的 executeAlgorithm() 方法。

4. 代码示例:电商促销活动

假设我们有一个电商系统,针对不同的促销活动(如无优惠、满减、打折),需要计算订单的最终价格。

不使用策略模式的写法 (原始写法):

java 复制代码
public class OrderOriginal {
    private String promotionType; // 活动类型: "NONE", "CASH_RETURN", "REBATE"
    private double originalPrice;

    public OrderOriginal(String promotionType, double originalPrice) {
        this.promotionType = promotionType;
        this.originalPrice = originalPrice;
    }

    public double calculateFinalPrice() {
        double finalPrice = originalPrice;
        if ("NONE".equals(promotionType)) { // 无优惠
            // finalPrice 保持原价
        } else if ("CASH_RETURN".equals(promotionType)) { // 满减,例如满200减20
            if (originalPrice >= 200) {
                finalPrice = originalPrice - 20;
            }
        } else if ("REBATE".equals(promotionType)) { // 打折,例如打9折
            finalPrice = originalPrice * 0.9;
        }
        // 如果再增加新的促销方式,比如"第二件半价",就需要继续修改这里的 if-else
        // 这违反了开闭原则,代码会越来越臃肿,难以维护
        return finalPrice;
    }

    public static void main(String[] args) {
        OrderOriginal order1 = new OrderOriginal("NONE", 150);
        System.out.println("无优惠,最终金额: " + order1.calculateFinalPrice());

        OrderOriginal order2 = new OrderOriginal("CASH_RETURN", 250);
        System.out.println("满200减20,最终金额: " + order2.calculateFinalPrice());

        OrderOriginal order3 = new OrderOriginal("REBATE", 300);
        System.out.println("打9折,最终金额: " + order3.calculateFinalPrice());
    }
}

缺点calculateFinalPrice 方法充满了 if-else 判断。每当需要增加一种新的促销策略时,都必须修改这个方法的内部逻辑,违反了"开闭原则"(对扩展开放,对修改关闭),并且使得这个类越来越庞大,难以维护。

使用策略模式的写法:

步骤1:定义策略接口 (PromotionStrategy)

java 复制代码
// 抽象策略:促销策略接口
interface PromotionStrategy {
    double applyPromotion(double originalPrice);
}

步骤2:创建具体策略类

java 复制代码
// 具体策略A:无优惠
class NoPromotionStrategy implements PromotionStrategy {
    @Override
    public double applyPromotion(double originalPrice) {
        System.out.println("执行无优惠策略");
        return originalPrice;
    }
}

// 具体策略B:满减策略 (例如:满200减20)
class CashReturnStrategy implements PromotionStrategy {
    private double conditionAmount;
    private double returnAmount;

    public CashReturnStrategy(double conditionAmount, double returnAmount) {
        this.conditionAmount = conditionAmount;
        this.returnAmount = returnAmount;
    }

    @Override
    public double applyPromotion(double originalPrice) {
        System.out.println("执行满" + conditionAmount + "减" + returnAmount + "策略");
        if (originalPrice >= conditionAmount) {
            return originalPrice - returnAmount;
        }
        return originalPrice;
    }
}

// 具体策略C:打折策略 (例如:9折)
class RebateStrategy implements PromotionStrategy {
    private double rebateRate; // 例如0.9代表9折

    public RebateStrategy(double rebateRate) {
        this.rebateRate = rebateRate;
    }

    @Override
    public double applyPromotion(double originalPrice) {
        System.out.println("执行" + (rebateRate * 10) + "折策略");
        return originalPrice * rebateRate;
    }
}

步骤3:创建上下文环境类 (OrderContext)

java 复制代码
// 上下文环境类
class OrderContext {
    private PromotionStrategy strategy;
    private double originalPrice;

    // 构造函数,传入订单原始价格
    public OrderContext(double originalPrice) {
        this.originalPrice = originalPrice;
    }

    // 设置具体策略
    public void setPromotionStrategy(PromotionStrategy strategy) {
        this.strategy = strategy;
    }

    // 调用策略方法计算价格
    public double getFinalPrice() {
        if (this.strategy == null) {
            // 默认策略或抛出异常
            System.out.println("未设置促销策略,默认无优惠");
            this.strategy = new NoPromotionStrategy(); 
        }
        return strategy.applyPromotion(originalPrice);
    }
}

步骤4:客户端使用

java 复制代码
public class StrategyPatternClient {
    public static void main(String[] args) {
        // 订单1:150元,使用无优惠策略
        OrderContext order1 = new OrderContext(150);
        order1.setPromotionStrategy(new NoPromotionStrategy());
        System.out.println("订单1最终金额: " + order1.getFinalPrice());
        System.out.println("--------------------");

        // 订单2:250元,使用满200减20策略
        OrderContext order2 = new OrderContext(250);
        order2.setPromotionStrategy(new CashReturnStrategy(200, 20));
        System.out.println("订单2最终金额: " + order2.getFinalPrice());
        System.out.println("--------------------");

        // 订单3:300元,使用打9折策略
        OrderContext order3 = new OrderContext(300);
        order3.setPromotionStrategy(new RebateStrategy(0.9));
        System.out.println("订单3最终金额: " + order3.getFinalPrice());
        System.out.println("--------------------");

        // 假设现在要新增一个"首单立减10元"的策略
        // 只需要新增一个 FirstOrderDiscountStrategy 类实现 PromotionStrategy 接口:
        // class FirstOrderDiscountStrategy implements PromotionStrategy {
        //     @Override
        //     public double applyPromotion(double originalPrice) {
        //         System.out.println("执行首单立减10元策略");
        //         return originalPrice - 10 > 0 ? originalPrice - 10 : 0;
        //     }
        // }
        // 然后客户端就可以这样使用:
        // OrderContext order4 = new OrderContext(100);
        // order4.setPromotionStrategy(new FirstOrderDiscountStrategy());
        // System.out.println("订单4最终金额: " + order4.getFinalPrice());
        // 此时,OrderContext 和 PromotionStrategy 接口都不需要修改,符合开闭原则。
    }
}

使用策略模式的优点:

  • 算法可以自由切换:在运行时可以方便地根据需求切换不同的促销策略。
  • 避免了多重条件判断 :消除了 OrderContext (或原先的 OrderOriginal) 中冗长的 if-elseswitch-case 语句。
  • 扩展性好 :增加新的促销策略非常容易,只需要添加一个新的具体策略类实现 PromotionStrategy 接口即可,完全符合开闭原则。
  • 每个算法都有自己的类,复用性提高:每个策略都是一个独立的类,职责清晰,易于测试和复用。
  • 代码更清晰:上下文类只负责协调,具体的业务逻辑在各个策略类中。

5. 策略模式的适用场景

  • 当一个系统需要在多种算法中选择一种时,可以将这些算法封装成独立的策略类。
  • 当一个对象拥有多种行为,并且这些行为在运行时根据不同情况动态选择时。
  • 当一个类中存在多个条件分支语句,且这些分支封装了不同的操作时(这是重构的信号)。
  • 当需要屏蔽算法规则或业务规则的复杂性,让客户端代码更简洁时。

6. 策略模式的优缺点

优点:

  • 策略类可以互相替换,使得算法的选择更加灵活。
  • 易于扩展,增加新的策略只需要添加新的策略类,符合开闭原则。
  • 避免了使用多重条件转移语句(if-else, switch)。
  • 提高了算法的保密性和安全性,因为具体的算法实现细节封装在策略类内部,客户端不需要了解。

缺点:

  • 策略类数量增多:每个具体策略都是一个类,如果策略很多,会导致类的数量增加。
  • 客户端必须知道所有的策略类:客户端(或配置代码)需要了解所有可用的策略以及它们之间的不同,才能在合适的时机选择合适的策略。可以通过结合工厂模式、依赖注入等方式来管理策略对象的创建和选择,以减轻客户端的职责。

二、责任链模式 (Chain of Responsibility Pattern)

1. 什么是责任链模式?

想象一下公司里的请假审批流程:你提交请假单,首先需要你的小组长审批。如果请假天数在小组长权限内(比如1天),小组长可以直接批准。如果天数较长(比如3天),小组长处理不了(或者说只能部分同意,然后上报),就需要将请求传递给部门经理审批。如果天数更长(比如7天),部门经理可能还需要将请求继续传递给总监审批。这个审批过程就像一条链条,你的请假请求在这条链上传递,每个审批人只关心自己职责范围内的事情,如果能处理就处理,不能处理就交给链上的下一个人。

责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止(或者所有对象都处理了它,或者链断了)。

简单来说,责任链模式就是为请求创建了一个接收者对象的链,请求会沿着链传递,直到链上的某个处理者处理它,或者请求穿过整个链条。

2. 生活中的例子

  • Java Web 中的 Filter 链:一个 HTTP 请求过来,可能需要经过多个 Filter 处理,如日志记录 Filter、权限校验 Filter、字符编码 Filter 等。每个 Filter 完成自己的任务后,可以选择将请求传递给链上的下一个 Filter,或者直接响应。
  • 异常处理机制 :Java 的 try-catch-finally 语句块,如果一个 try 块中发生异常,会先被第一个 catch 块尝试捕获,如果类型不匹配或处理不了,可以重新抛出,由外层的 catch 或JVM默认异常处理器(链的末端)处理。
  • OA 系统的审批流程:采购申请、报销申请等,通常需要经过多个级别的审批者依次审批。
  • 事件冒泡/捕获机制:在图形用户界面(GUI)编程中,一个组件上的事件(如点击)可能会先由该组件处理,如果未处理,则向上传递给其父组件处理。

3. 责任链模式的结构

责任链模式主要包含以下角色:

  • Handler (抽象处理者) :定义了一个处理请求的接口(通常是一个方法 handleRequest(request)),并且持有一个指向链中下一个处理者(后继者)的引用。
  • ConcreteHandler (具体处理者) :实现了 Handler 接口。它负责处理它所能处理的请求。在 handleRequest 方法中,它会判断自己是否能处理该请求:
    • 如果可以处理,则处理请求,并可能决定是否继续传递给下一个处理者。
    • 如果不能处理,则将请求转发给它的后继者(如果存在)。
  • Client (客户端):创建处理链(即组装 ConcreteHandler 对象),并向链头的处理者发起请求。客户端通常不关心请求最终由哪个具体处理者处理。

(用文字描述结构关键点)

  • 你会有一个 Handler 接口或抽象类,里面定义了一个处理请求的方法 handleRequest(request),以及一个设置下一个处理者的方法 setNextHandler(handler)。通常,Handler 内部会有一个 Handler nextHandler 成员变量来保存下一个处理者的引用。
  • 然后有很多个 ConcreteHandlerA, ConcreteHandlerB 类,它们实现了 Handler。在 handleRequest 方法中,它们会先判断自己能否处理这个请求。如果能,就处理,并决定是否到此为止;如果不能(或者处理完还想让别人也处理),就调用 nextHandler.handleRequest(request) 把请求传递下去(当然,要先判断 nextHandler 是否为空)。
  • 客户端会创建这些 ConcreteHandler 对象,并调用它们的 setNextHandler 方法把它们串联起来形成一条链。然后客户端将请求发送给链的第一个处理者。

4. 代码示例:敏感词过滤器链

假设我们需要对用户发表的评论进行敏感词过滤,不同类型的敏感词(如政治类、广告类)由不同的过滤器处理。每个过滤器处理完自己负责的部分后,将内容交给下一个过滤器继续处理。

不使用责任链模式的写法 (原始写法):

java 复制代码
public class CommentProcessorOriginal {
    public String filter(String comment) {
        String processedComment = comment;

        // 过滤政治敏感词
        if (processedComment.contains("敏感词A")) {
            processedComment = processedComment.replace("敏感词A", "***");
        }
        // 过滤广告词
        if (processedComment.contains("广告词X")) {
            processedComment = processedComment.replace("广告词X", "$$$");
        }
        // 如果增加新的过滤规则,比如色情词过滤,就需要不断修改这个方法
        // 职责不单一,代码耦合度高
        return processedComment;
    }

    public static void main(String[] args) {
        CommentProcessorOriginal processor = new CommentProcessorOriginal();
        String comment = "这是一条包含敏感词A和广告词X的评论。";
        String filteredComment = processor.filter(comment);
        System.out.println("原始评论: " + comment);
        System.out.println("过滤后评论: " + filteredComment);
    }
}

缺点filter 方法职责过重,包含了所有类型的过滤逻辑。新增或修改过滤规则都需要改动这个方法,违反开闭原则,且代码会越来越复杂和难以维护。

使用责任链模式的写法:

步骤1:定义抽象处理者 (CommentFilter)

java 复制代码
// 抽象处理者:评论过滤器
abstract class CommentFilter {
    protected CommentFilter nextFilter; // 指向下一个过滤器

    public void setNextFilter(CommentFilter nextFilter) {
        this.nextFilter = nextFilter;
    }

    // 处理请求的方法
    // 返回处理后的评论内容,或者也可以设计成直接修改传入的 Comment 对象
    public abstract String doFilter(String comment);
}

步骤2:创建具体处理者类

java 复制代码
// 具体处理者A:政治敏感词过滤器
class PoliticalWordFilter extends CommentFilter {
    @Override
    public String doFilter(String comment) {
        System.out.println("执行政治敏感词过滤...");
        String filteredComment = comment.replace("敏感词A", "***").replace("反动", "##");
        
        // 如果有下一个过滤器,则继续传递给下一个过滤器处理
        if (nextFilter != null) {
            return nextFilter.doFilter(filteredComment);
        }
        return filteredComment; // 如果是链的末尾,则返回结果
    }
}

// 具体处理者B:广告词过滤器
class AdvertisementWordFilter extends CommentFilter {
    @Override
    public String doFilter(String comment) {
        System.out.println("执行广告词过滤...");
        String filteredComment = comment.replace("广告词X", "$$$").replace("优惠券", "###");
        
        if (nextFilter != null) {
            return nextFilter.doFilter(filteredComment);
        }
        return filteredComment;
    }
}

// 具体处理者C:特殊字符过滤器 (新增的)
class SpecialCharacterFilter extends CommentFilter {
    @Override
    public String doFilter(String comment) {
        System.out.println("执行特殊字符过滤...");
        String filteredComment = comment.replaceAll("[<>]", ""); // 移除尖括号
        
        if (nextFilter != null) {
            return nextFilter.doFilter(filteredComment);
        }
        return filteredComment;
    }
}

步骤3:客户端构建责任链并使用

java 复制代码
public class ChainOfResponsibilityClient {
    public static void main(String[] args) {
        String comment = "这是一条<包含>敏感词A、广告词X和反动言论的评论,快来领取优惠券!";
        System.out.println("原始评论: " + comment);
        System.out.println("--------------------");

        // 构建过滤器链
        CommentFilter politicalFilter = new PoliticalWordFilter();
        CommentFilter advertisementFilter = new AdvertisementWordFilter();
        CommentFilter specialCharFilter = new SpecialCharacterFilter();

        // 设置链的顺序: 特殊字符 -> 政治敏感 -> 广告
        // 顺序很重要,不同的顺序可能导致不同的结果
        specialCharFilter.setNextFilter(politicalFilter);
        politicalFilter.setNextFilter(advertisementFilter);
        // advertisementFilter 是链的末端,它的 nextFilter 是 null

        // 从链头开始处理
        String filteredComment = specialCharFilter.doFilter(comment);
        System.out.println("--------------------");
        System.out.println("过滤后评论: " + filteredComment);

        // 优点:
        // 1. 新增过滤器非常方便,例如新增一个Emoji过滤器,只需要实现CommentFilter,然后插入链中即可。
        //    现有的过滤器代码完全不需要修改。
        // 2. 每个过滤器的职责单一,易于维护和测试。
        // 3. 过滤器的顺序可以灵活调整。
    }
}

使用责任链模式的优点:

  • 降低耦合度:请求的发送者和接收者解耦。发送者不需要知道请求会被哪个接收者处理,只需将请求发送给链的第一个处理者。
  • 增强了系统的可扩展性:可以很容易地增加新的处理者到链中,或改变链中处理者的顺序,符合开闭原则。
  • 增强了给对象指派职责的灵活性:通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任,以及动态地改变责任的顺序。
  • 简化了对象:使得每个处理者对象不需要知道链的整体结构,只需要知道它的后继者。
  • 每个类只专注于自己的职责:每个具体处理者类只负责处理它能处理的请求,职责清晰。

5. 责任链模式的适用场景

  • 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时动态确定(即请求的处理者不确定)。
  • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
  • 可动态指定一组对象处理请求,或者添加新的处理者到这条链上。
  • 例如:Web 应用的过滤器链 (Servlet Filters, Spring Interceptors)、UI 事件的传递与处理、工作流审批系统、日志记录器的不同级别处理。

6. 责任链模式的优缺点

优点:

  • 请求的发送者和接收者解耦。
  • 可以动态地组合责任链,灵活地增加或修改处理一个请求的结构和顺序。
  • 易于扩展新的请求处理者。
  • 每个处理者职责单一。

缺点:

  • 请求不一定被处理:不能保证请求一定会被链中的某个处理者处理。如果没有任何处理者处理该请求,请求可能会到达链的末尾仍未被处理(需要有相应的默认处理机制或明确链尾行为)。
  • 性能问题:如果责任链过长,或者每个处理者的处理逻辑都比较耗时,请求在链中逐级传递可能会对性能产生影响。
  • 调试不方便:由于请求的路径是动态组合的,如果责任链比较长,在调试时可能需要跟踪整个链条的执行过程,增加了调试的复杂性。
  • 可能导致链的构建比较复杂:尤其是在复杂的场景下,链的组织和维护可能需要仔细设计。

三、策略模式 vs. 责任链模式

现在我们来对比一下这两种设计模式,希望能帮你更好地理解它们的区别和适用场景。

特性 策略模式 (Strategy Pattern) 责任链模式 (Chain of Responsibility Pattern)
核心思想 封装可互换的行为(算法),客户端或上下文主动选择一个策略来执行。 构建对象链,请求在链上自动传递,直到被某个对象处理(或链结束)。
目的 使得算法可以独立于使用它的客户端而变化。提供多种方案供选择。 避免请求发送者与接收者耦合,让多个对象都有机会处理请求,形成处理流程。
处理者数量 一个请求通常只由一个选定的具体策略对象处理。 一个请求可能被链上的多个处理者依次处理 (如果设计如此,如Filter),或被某一个处理者完整处理后停止传递(如审批流程)。
对象间关系 Context 持有对 Strategy 的引用。策略之间通常是平行的、独立的,可互相替换。 Handler 持有对下一个 Handler 的引用,形成链式(线性)结构。处理者之间有明确的先后顺序。
选择/触发方式 客户端或 Context 在运行时明确选择或设置一个具体的策略。 请求沿着链自动传递,由链上的对象自行判断是否处理以及是否继续传递。
关注点 如何封装一组可互换的算法,以及如何根据情况选择和切换算法。 如何组织和传递请求,如何解耦请求的发送和接收,以及如何让多个对象协同处理请求。
数据流向 Context 将任务委托给(或调用)选定的 Strategy 请求从链头开始,沿着链传递给后续的 Handler
是否保证处理 选定的策略一定会执行其操作(除非策略本身设计为不执行或有条件执行)。 不一定保证请求会被处理(如果链中没有合适的处理者且链尾没有默认处理)。
典型场景 多种支付方式、多种排序算法、多种出行路线。 Web请求过滤器链、审批流程、日志分级处理、异常捕获链。
类比 像一个工具箱,里面有各种工具(策略),用的时候选一个合适的。 像工厂流水线,产品(请求)经过一道道工序(处理者)。

何时选择哪种模式?

  • 选择策略模式的场景:

    • 当你有一系列相关的算法或行为,它们可以互换使用。
    • 当你希望客户端能够在运行时选择使用哪种算法/行为。
    • 当你希望将算法的实现细节与使用算法的代码分离开来,避免大量的 if-elseswitch 语句。
    • 核心是"选择":针对一个任务,有多种独立的、平等的处理方案,你需要根据情况选择一种。
  • 选择责任链模式的场景:

    • 当一个请求需要被多个对象中的一个或多个处理,但你事先不知道应该由哪个对象来处理,或者希望处理者可以动态组合。
    • 当你希望将请求的发送者和接收者解耦。
    • 当你希望一个请求可以被多个对象按顺序部分处理(像过滤器那样)。
    • 当你希望能够动态地改变处理者的顺序或增删处理者。
    • 核心是"传递"和"分担责任":一个请求过来,需要经过一系列可能的处理环节,每个环节决定自己是否处理以及是否继续传递。

一个简单的区分思路:

  • 策略模式是"我有多种方法可以做这件事,你(或我根据情况)选一种来用吧!" (One of many options is CHOSEN)
  • 责任链模式是"这件事来了,大家按顺序看看谁能处理,或者每个人都处理一下自己负责的部分。" (Request is PASSED along a chain)

四、总结重点

对于初学者来说,理解设计模式的关键在于把握其核心思想、结构和适用场景。

  • 策略模式 (Strategy Pattern)

    • 核心:封装一组可以相互替换的算法(策略)。
    • 目的:使得算法的选择可以独立于使用算法的客户端。
    • 关键结构:抽象策略 (Interface/Abstract Class),具体策略 (Concrete Classes),上下文 (Context class holding a strategy instance)。
    • 优点:易于扩展新策略、消除条件语句、算法独立封装。
    • 思考:当一件事情有多种处理"方案"或"策略"时,并且这些方案可以互换,可以考虑策略模式。客户端通常主动选择或被配置使用某个特定策略。
  • 责任链模式 (Chain of Responsibility Pattern)

    • 核心:将请求的发送者和接收者解耦,使多个对象都有机会处理请求,并将这些对象连成一条链。
    • 目的:请求沿着链传递,直到有一个对象处理它为止(或到达链尾)。
    • 关键结构:抽象处理者 (Handler Interface/Abstract Class with a successor reference),具体处理者 (Concrete Handlers implementing the logic and forwarding)。
    • 优点:解耦发送者和接收者、灵活组合处理流程、职责单一化。
    • 思考:当一个请求的处理过程可能需要经过多个步骤/对象,这些步骤/对象可以动态组合,并且每个步骤/对象只关心自己的部分责任时,可以考虑责任链模式。请求通常是自动在链上传递。

学习建议:

  1. 多看例子:结合生活中的例子和代码例子去理解模式的意图和结构。
  2. 动手实践:尝试在你自己的小型项目或练习中运用这些模式,这是加深理解的最好方式。
  3. 思考辨析:对于相似的模式(如策略模式和状态模式,责任链模式和装饰器模式等),多对比它们的意图、结构和适用场景的差异。
  4. 循序渐进:设计模式的学习是一个逐步深入的过程,不必急于求成。先理解基础的,再逐步学习更复杂的组合和应用。
  5. 关注"变化点":设计模式往往是为了封装系统中可能发生变化的部分,理解一个模式要解决的是哪种类型的变化,有助于你判断何时使用它。

希望这篇笔记能帮助你更好地理解策略模式和责任链模式!在后续的开发工作中,尝试用设计模式的眼光去审视和设计你的代码,你会发现它们能让你的代码更加优雅、健壮和易于维护。

相关推荐
之之为知知1 小时前
数学笔记三:特殊矩阵
笔记·学习·线性代数·算法·职场和发展·矩阵·职场发展
霸王蟹1 小时前
React 泛型组件:用TS来打造灵活的组件。
前端·学习·react.js·typescript·前端框架
代码小将1 小时前
java方法重写学习笔记
java·笔记·学习
行走的bug...2 小时前
makefile学习笔记
linux·笔记·学习
大苏打seven3 小时前
Docker学习笔记:基础知识
笔记·学习·docker
sensen_kiss4 小时前
CPT208 Human-Centric Computing 人机交互 Pt.5 原型保真度和维度
学习·人机交互
kovlistudio4 小时前
大模型应用开发第五讲:成熟度模型:从ChatGPT(L2)到未来自主Agent(L4)
人工智能·深度学习·学习·机器学习·chatgpt·tensorflow
sensen_kiss4 小时前
CPT208 Human-Centric Computing 人机交互 Pt.7 交互和交互界面
学习·人机交互·交互
hello kitty w4 小时前
Python学习(1) ----- Python的文件读取和写入
java·python·学习
五步晦暝5 小时前
【ExcelVBA 】类模块学习从入门到放弃
java·前端·学习