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

发布于:2025-05-28 ⋅ 阅读:(21) ⋅ 点赞:(0)

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

你好!作为一名 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. 代码示例:电商促销活动

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

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

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)

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

步骤2:创建具体策略类

// 具体策略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)

// 上下文环境类
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:客户端使用

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. 代码示例:敏感词过滤器链

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

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

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)

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

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

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

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

// 具体处理者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:客户端构建责任链并使用

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. 关注“变化点”:设计模式往往是为了封装系统中可能发生变化的部分,理解一个模式要解决的是哪种类型的变化,有助于你判断何时使用它。

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


网站公告

今日签到

点亮在社区的每一天
去签到