大家好,欢迎来到设计模式系列文章(基础篇)的第二十六篇内容。在上一篇中,我们学习了行为型模式的第十五种常用模式——解释器模式,其核心是定义特定语言的语法规则,将语法拆解为解释单元,通过构建抽象语法树递归解析,实现表达式的解释与执行,广泛应用于表达式解析、规则引擎、模板引擎等场景。今天,我们将学习行为型模式的第十六种常用模式——访问者模式,它的核心是定义一个作用于对象结构中各元素的操作,使我们可以在不改变各元素类的前提下,灵活定义作用于这些元素的新操作。

在日常开发中,我们经常会遇到这样的场景:一个固定的数据结构(如集合、树结构)中包含多种不同类型的元素,我们需要对这些元素执行多种不同的操作,且后续可能会新增更多操作。比如一个电商系统的商品列表(数据结构),包含电子产品、服装、食品等不同类型的商品(元素),我们需要对这些商品执行计算总价、生成报表、统计库存等操作,且后续可能会新增折扣计算、销量统计等新操作。如果不使用访问者模式,我们通常会在每个商品类中添加对应的操作方法,这样一来,新增操作时就需要修改所有商品类的代码,违背开闭原则,且操作逻辑分散在各个元素类中,难以维护和扩展。

而访问者模式,通过将“数据结构”与“操作逻辑”彻底分离,将所有操作逻辑封装在访问者类中,元素类仅负责提供接受访问者的接口,不包含任何操作逻辑。当需要新增操作时,只需新增一个访问者类,无需修改任何元素类和数据结构;当需要遍历数据结构中的所有元素时,只需让访问者依次访问每个元素,就能执行对应的操作。这种方式不仅实现了数据结构与操作的解耦,还让操作逻辑更加集中,便于维护和扩展,尤其适用于数据结构固定、操作频繁变化的场景。今天,我们就从核心定义、结构、实战实现、场景对比、避坑指南全维度讲解,帮大家彻底掌握这种“分离数据结构与操作”的实用设计模式。

一、访问者模式的核心定义与设计初衷

1. 核心定义
访问者模式(Visitor Pattern):定义一个作用于某对象结构中的各元素的操作接口,使得在不改变各元素类的前提下,可定义作用于这些元素的新操作。访问者模式的核心是分离数据结构与操作逻辑,将操作逻辑封装在访问者中,元素接受访问者的访问并执行对应操作。
通俗理解:访问者模式就像我们去博物馆参观(对应数据结构),博物馆里有绘画、雕塑、文物等不同类型的展品(对应元素),我们(对应访问者)可以对每类展品执行不同的操作——欣赏、拍照、记录讲解。展品本身不需要知道我们要做什么操作,只需“接受”我们的访问;而我们可以根据自己的需求,新增不同的操作(如写生、录音),无需修改展品本身。在这个过程中,展品(元素)是固定的,而我们的操作(访问者)是可以灵活扩展的,完美体现了“数据结构与操作分离”的核心思想。

2. 设计初衷(解决的核心问题)
访问者模式的出现,核心是解决“数据结构固定、操作频繁变化,且新增操作需修改元素类”的痛点,具体解决3个核心问题:

  • 分离数据与操作:将数据结构(元素集合)与操作逻辑(访问者)分离,避免操作逻辑分散在各个元素类中,便于维护;
  • 支持操作灵活扩展:新增操作时,只需新增访问者类,无需修改元素类和数据结构,符合开闭原则;
  • 集中管理操作逻辑:将同一类操作的逻辑集中在一个访问者类中,便于代码复用和统一维护(如所有统计相关的操作都放在统计访问者中)。

3. 设计原则适配
访问者模式严格贴合面向对象设计核心原则,尤其在“开闭原则”和“单一职责原则”上表现突出,是实现数据与操作分离的最佳实践:

  • 单一职责原则:每个访问者类只负责一类操作(如计算总价访问者、生成报表访问者),每个元素类只负责存储自身数据并提供接受访问的接口,职责单一;
  • 开闭原则:新增操作时,只需新增访问者类,无需修改元素类和数据结构;修改操作时,只需修改对应访问者类,不影响其他代码;
  • 依赖倒转原则:元素类依赖抽象访问者接口,不依赖具体访问者;访问者依赖抽象元素接口,不依赖具体元素类,便于替换和扩展;
  • 迪米特法则(最少知道原则):元素类无需知道访问者的具体操作逻辑,只需提供接受访问的接口;访问者无需知道数据结构的具体实现,只需遍历元素并执行操作。

二、访问者模式的核心结构(5个核心角色)

访问者模式的结构围绕“数据结构与操作分离”展开,核心包含5个角色,各司其职、协同完成操作的执行与扩展,我们以“电商商品列表操作”为场景,逐一拆解角色职责与交互逻辑:

1. 抽象访问者(Abstract Visitor)
所有具体访问者的抽象父类或接口,定义了访问者对每种元素的访问方法,方法名通常与元素类型对应(如visitElectronic、visitClothing),每个方法接受对应类型的元素作为参数,用于执行该元素的对应操作。抽象访问者规范了访问者的操作接口,确保所有具体访问者都实现对所有元素的访问方法。对应电商场景中的“商品操作接口”,定义对电子产品、服装、食品的访问方法。

2. 具体访问者(Concrete Visitor)
实现抽象访问者接口,封装了对每种元素的具体操作逻辑,每个访问方法对应一种元素的一种操作。一个具体访问者对应一类操作(如计算总价、生成报表),新增操作时,只需新增一个具体访问者类。对应电商场景中的“计算总价访问者”“生成报表访问者”,分别实现对各类商品的总价计算和报表生成操作。

3. 抽象元素(Abstract Element)
所有具体元素的抽象父类或接口,定义了元素接受访问者访问的核心方法(通常称为accept方法),该方法接受一个抽象访问者作为参数,通过调用访问者的对应访问方法,实现访问者对元素的操作。抽象元素屏蔽了具体元素的实现细节,让访问者可以统一访问所有元素。对应电商场景中的“商品接口”,定义accept方法,接受商品操作访问者。

4. 具体元素(Concrete Element)
实现抽象元素接口,存储自身的数据信息,并实现accept方法。在accept方法中,调用访问者针对当前元素类型的访问方法,将自身作为参数传递给访问者,让访问者执行对该元素的操作。具体元素不包含任何操作逻辑,仅负责接受访问者的访问。对应电商场景中的“电子产品”“服装”“食品”类,存储商品的价格、库存等信息,实现accept方法。

5. 对象结构(Object Structure)
用于存储和管理所有元素对象,提供遍历元素的方法,供访问者依次访问每个元素。对象结构可以是集合、列表、树等数据结构,其核心职责是组织元素,让访问者能够高效地遍历所有元素并执行操作。对应电商场景中的“商品列表”,存储所有商品元素,提供遍历商品的方法。
核心关系总结:抽象访问者定义操作规范,具体访问者实现操作逻辑;抽象元素定义接受访问的接口,具体元素接受访问并触发访问者的操作;对象结构管理元素并提供遍历接口。访问者通过对象结构遍历所有元素,每个元素调用访问者的对应方法,实现操作的执行;新增操作只需新增具体访问者,无需修改元素和对象结构。

三、访问者模式的核心逻辑与执行流程

访问者模式的核心逻辑是“分离数据与操作、接受访问、遍历执行”,标准执行流程分为六步,全程实现数据结构与操作逻辑的解耦,逻辑闭环,我们以“电商商品列表计算总价”为例,拆解执行流程:

  1. 定义抽象元素接口:声明accept方法,接受抽象访问者作为参数;
  2. 实现具体元素类:存储自身数据,实现accept方法,调用访问者对应类型的访问方法;
  3. 定义抽象访问者接口:声明对每种具体元素的访问方法;
  4. 实现具体访问者类:实现抽象访问者的所有访问方法,封装对每种元素的具体操作逻辑(如计算商品价格);
  5. 构建对象结构:创建对象结构,添加所有具体元素(商品),提供遍历元素的方法;
  6. 执行操作:创建具体访问者对象,通过对象结构遍历所有元素,每个元素接受访问者的访问,执行对应操作,最终得到操作结果(如商品总价)。
    关键要点:具体元素的accept方法是核心,它将自身传递给访问者,触发访问者的对应操作,实现“元素主动接受访问”;对象结构负责组织元素,简化访问者的遍历操作;新增操作时,只需新增具体访问者,无需修改元素和对象结构,体现了开闭原则的优势。

四、访问者模式的实战实现(电商商品列表操作场景)

我们以高频的电商商品列表操作为场景,使用Java代码实现访问者模式,商品列表(对象结构)包含电子产品、服装、食品三种具体元素,实现两种操作:计算所有商品的总价(具体访问者1)、生成商品库存报表(具体访问者2),直观体现访问者模式“分离数据结构与操作、灵活扩展”的核心优势。
场景说明:电子产品包含名称、价格、库存、保修期信息;服装包含名称、价格、库存、尺码信息;食品包含名称、价格、库存、保质期信息;商品列表存储所有商品,支持遍历商品;计算总价访问者负责计算所有商品的价格总和;库存报表访问者负责生成所有商品的库存信息报表;后续新增“折扣计算”操作时,只需新增访问者,无需修改商品类和商品列表。

1. 第一步:定义抽象元素接口(Abstract Element)

// 抽象元素:商品接口,定义接受访问者的方法
public interface Product {
    // 接受访问者访问
    void accept(ProductVisitor visitor);
}

2. 第二步:实现具体元素类(Concrete Element)

// 具体元素1:电子产品
public class ElectronicProduct implements Product {
    private String name; // 商品名称
    private double price; // 商品价格
    private int stock; // 库存数量
    private int warrantyPeriod; // 保修期(月)

    // 构造方法:初始化商品信息
    public ElectronicProduct(String name, double price, int stock, int warrantyPeriod) {
        this.name = name;
        this.price = price;
        this.stock = stock;
        this.warrantyPeriod = warrantyPeriod;
    }

    // 接受访问者访问,调用访问者针对电子产品的方法
    @Override
    public void accept(ProductVisitor visitor) {
        visitor.visitElectronic(this);
    }

    // getter方法:供访问者获取商品信息
    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public int getStock() {
        return stock;
    }

    public int getWarrantyPeriod() {
        return warrantyPeriod;
    }
}

// 具体元素2:服装
public class ClothingProduct implements Product {
    private String name;
    private double price;
    private int stock;
    private String size; // 尺码(S/M/L/XL)

    public ClothingProduct(String name, double price, int stock, String size) {
        this.name = name;
        this.price = price;
        this.stock = stock;
        this.size = size;
    }

    @Override
    public void accept(ProductVisitor visitor) {
        visitor.visitClothing(this);
    }

    // getter方法
    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public int getStock() {
        return stock;
    }

    public String getSize() {
        return size;
    }
}

// 具体元素3:食品
public class FoodProduct implements Product {
    private String name;
    private double price;
    private int stock;
    private String shelfLife; // 保质期(如“6个月”)

    public FoodProduct(String name, double price, int stock, String shelfLife) {
        this.name = name;
        this.price = price;
        this.stock = stock;
        this.shelfLife = shelfLife;
    }

    @Override
    public void accept(ProductVisitor visitor) {
        visitor.visitFood(this);
    }

    // getter方法
    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public int getStock() {
        return stock;
    }

    public String getShelfLife() {
        return shelfLife;
    }
}

3. 第三步:定义抽象访问者接口(Abstract Visitor)

// 抽象访问者:商品操作接口,定义对每种商品的访问方法
public interface ProductVisitor {
    // 访问电子产品
    void visitElectronic(ElectronicProduct electronic);
    // 访问服装
    void visitClothing(ClothingProduct clothing);
    // 访问食品
    void visitFood(FoodProduct food);
}

4. 第四步:实现具体访问者类(Concrete Visitor)

// 具体访问者1:计算总价访问者,负责计算所有商品的总价
public class TotalPriceVisitor implements ProductVisitor {
    private double totalPrice = 0.0; // 商品总价

    // 访问电子产品,累加价格
    @Override
    public void visitElectronic(ElectronicProduct electronic) {
        totalPrice += electronic.getPrice() * electronic.getStock();
        System.out.println("已计算电子产品【" + electronic.getName() + "】价格,单价:" + electronic.getPrice() + ",库存:" + electronic.getStock());
    }

    // 访问服装,累加价格
    @Override
    public void visitClothing(ClothingProduct clothing) {
        totalPrice += clothing.getPrice() * clothing.getStock();
        System.out.println("已计算服装【" + clothing.getName() + "】价格,单价:" + clothing.getPrice() + ",库存:" + clothing.getStock());
    }

    // 访问食品,累加价格
    @Override
    public void visitFood(FoodProduct food) {
        totalPrice += food.getPrice() * food.getStock();
        System.out.println("已计算食品【" + food.getName() + "】价格,单价:" + food.getPrice() + ",库存:" + food.getStock());
    }

    // 获取计算后的总价
    public double getTotalPrice() {
        return totalPrice;
    }
}

// 具体访问者2:库存报表访问者,负责生成商品库存报表
public class StockReportVisitor implements ProductVisitor {
    private StringBuilder report = new StringBuilder(); // 库存报表内容

    @Override
    public void visitElectronic(ElectronicProduct electronic) {
        report.append("电子产品:")
              .append(electronic.getName())
              .append(",库存:")
              .append(electronic.getStock())
              .append(",保修期:")
              .append(electronic.getWarrantyPeriod())
              .append("个月\n");
    }

    @Override
    public void visitClothing(ClothingProduct clothing) {
        report.append("服装:")
              .append(clothing.getName())
              .append(",库存:")
              .append(clothing.getStock())
              .append(",尺码:")
              .append(clothing.getSize())
              .append("\n");
    }

    @Override
    public void visitFood(FoodProduct food) {
        report.append("食品:")
              .append(food.getName())
              .append(",库存:")
              .append(food.getStock())
              .append(",保质期:")
              .append(food.getShelfLife())
              .append("\n");
    }

    // 获取生成的库存报表
    public String getStockReport() {
        return "=== 商品库存报表 ===\n" + report.toString();
    }
}

5. 第五步:定义对象结构(Object Structure)

// 对象结构:商品列表,管理所有商品元素,提供遍历方法
import java.util.ArrayList;
import java.util.List;

public class ProductList {
    // 存储所有商品元素
    private List<Product> productList = new ArrayList<>();

    // 添加商品
    public void addProduct(Product product) {
        productList.add(product);
    }

    // 移除商品
    public void removeProduct(Product product) {
        productList.remove(product);
    }

    // 接受访问者访问,遍历所有商品,让每个商品接受访问
    public void accept(ProductVisitor visitor) {
        for (Product product : productList) {
            product.accept(visitor);
        }
    }
}

6. 第六步:客户端测试

// 客户端测试:电商商品列表操作场景
public class VisitorPatternTest {
    public static void main(String[] args) {
        // 1. 创建具体商品元素
        Product phone = new ElectronicProduct("智能手机", 2999.0, 50, 12);
        Product shirt = new ClothingProduct("纯棉衬衫", 199.0, 100, "M");
        Product milk = new FoodProduct("纯牛奶", 60.0, 200, "6个月");

        // 2. 创建对象结构(商品列表),添加商品
        ProductList productList = new ProductList();
        productList.addProduct(phone);
        productList.addProduct(shirt);
        productList.addProduct(milk);

        // 3. 测试1:使用计算总价访问者,计算所有商品总价
        System.out.println("=== 测试计算商品总价 ===");
        TotalPriceVisitor totalPriceVisitor = new TotalPriceVisitor();
        productList.accept(totalPriceVisitor);
        System.out.println("所有商品总价:" + totalPriceVisitor.getTotalPrice() + "元\n");

        // 4. 测试2:使用库存报表访问者,生成库存报表
        System.out.println("=== 测试生成库存报表 ===");
        StockReportVisitor stockReportVisitor = new StockReportVisitor();
        productList.accept(stockReportVisitor);
        System.out.println(stockReportVisitor.getStockReport());

        // 5. 测试3:新增操作(无需修改现有代码,新增访问者即可)
        System.out.println("=== 测试新增折扣计算操作 ===");
        DiscountVisitor discountVisitor = new DiscountVisitor();
        productList.accept(discountVisitor);
        System.out.println("折扣后商品总价:" + discountVisitor.getDiscountTotalPrice() + "元");
    }

    // 新增具体访问者:折扣计算访问者(新增操作,无需修改现有商品类和商品列表)
    static class DiscountVisitor implements ProductVisitor {
        private double discountTotalPrice = 0.0; // 折扣后总价
        private double discount = 0.8; // 统一折扣8折(可根据商品类型调整)

        @Override
        public void visitElectronic(ElectronicProduct electronic) {
            // 电子产品折扣8折
            double discountPrice = electronic.getPrice() * electronic.getStock() * discount;
            discountTotalPrice += discountPrice;
        }

        @Override
        public void visitClothing(ClothingProduct clothing) {
            // 服装折扣8折
            double discountPrice = clothing.getPrice() * clothing.getStock() * discount;
            discountTotalPrice += discountPrice;
        }

        @Override
        public void visitFood(FoodProduct food) {
            // 食品折扣9折
            double discountPrice = food.getPrice() * food.getStock() * 0.9;
            discountTotalPrice += discountPrice;
        }

        public double getDiscountTotalPrice() {
            return discountTotalPrice;
        }
    }
}

运行结果

=== 测试计算商品总价 ===
已计算电子产品【智能手机】价格,单价:2999.0,库存:50
已计算服装【纯棉衬衫】价格,单价:199.0,库存:100
已计算食品【纯牛奶】价格,单价:60.0,库存:200
所有商品总价:189850.0元

=== 测试生成库存报表 ===
=== 商品库存报表 ===
电子产品:智能手机,库存:50,保修期:12个月
服装:纯棉衬衫,库存:100,尺码:M
食品:纯牛奶,库存:200,保质期:6个月

=== 测试新增折扣计算操作 ===
折扣后商品总价:162370.0元

从运行结果可以看出,访问者模式成功实现了数据结构(商品列表)与操作逻辑(计算总价、生成报表、折扣计算)的分离:商品类(元素)仅负责存储数据和接受访问,不包含任何操作逻辑;所有操作逻辑都封装在访问者类中,新增“折扣计算”操作时,只需新增DiscountVisitor类,无需修改任何商品类和商品列表,完美体现了开闭原则。同时,操作逻辑集中在访问者类中,便于维护和复用,比如计算总价和折扣计算的逻辑分别在两个访问者中,互不干扰。

五、访问者模式的高频应用场景

访问者模式适用于所有数据结构固定、操作频繁变化,且需要在不修改元素类的前提下扩展操作的业务场景,核心作用是分离数据与操作,实现操作的灵活扩展,以下是四大高频落地场景:

1. 数据统计与报表生成(最经典应用)
数据结构固定(如商品列表、用户列表),需要对数据执行多种统计、报表生成操作,且后续可能新增更多统计维度:

  • 电商商品管理:商品列表固定,需要计算总价、统计库存、生成销售报表、计算折扣等操作;
  • 用户数据统计:用户列表固定,需要统计用户年龄分布、消费金额、活跃度等多种指标;
  • 财务数据管理:财务明细列表固定,需要生成利润报表、成本报表、税务报表等。

2. 对象结构遍历与操作
复杂对象结构(如树、组合结构)固定,需要对结构中的每个元素执行不同的操作,且操作逻辑频繁变化:

  • 树形结构操作:文件系统(目录和文件构成树形结构),需要执行遍历文件、计算文件大小、搜索文件等操作;
  • 组合模式结合使用:组合模式构建的对象结构(如部门组织架构),需要统计部门人数、计算部门薪资总额等操作。

3. 规则引擎与业务校验
业务对象结构固定,需要对对象执行多种规则校验、业务逻辑判断,且规则可能频繁更新:

  • 订单规则校验:订单对象结构固定,需要校验订单金额、收货地址、支付状态等多种规则;
  • 用户权限校验:用户对象结构固定,需要校验用户角色、操作权限、数据访问权限等多种规则。

4. 框架底层与工具类设计
主流开源框架和工具类中,大量使用访问者模式实现数据与操作的分离,提升框架的灵活性:

  • Java集合框架:Iterator迭代器本质是一种简化的访问者模式,迭代器(访问者)遍历集合(对象结构)中的元素,执行遍历操作;
  • Spring框架:Spring的BeanDefinitionVisitor,用于访问BeanDefinition的各个属性,执行属性修改、校验等操作;
  • 解析器框架:XML解析、JSON解析框架中,访问者模式用于遍历解析树中的节点,执行解析和处理操作。

六、访问者模式 vs 解释器模式(重点区分)

访问者模式与上一篇学习的解释器模式,都属于行为型模式,且都涉及“逻辑的封装与执行”,但核心目标、使用场景、核心逻辑完全不同,极易混淆,通过表格清晰对比,帮大家彻底区分:

对比维度 访问者模式 解释器模式
核心目标 分离数据结构与操作逻辑,实现操作的灵活扩展 解析特定语言的语法规则,实现表达式的解释与执行
核心逻辑 访问者遍历对象结构中的元素,元素接受访问并触发访问者的操作 将语法规则拆解为解释单元,构建抽象语法树,递归解析执行
适用场景 数据结构固定、操作频繁变化(关注“操作扩展”) 表达式解析、规则引擎(关注“语法解析”)
核心角色 抽象访问者、具体访问者、抽象元素、具体元素、对象结构 抽象表达式、终结符表达式、非终结符表达式、环境
核心关注点 数据与操作的分离,实现操作的灵活扩展 语法规则的拆解与解析,实现语言的解释与执行

一句话总结:访问者模式管“操作扩展”,解释器模式管“语法解析”;数据结构固定、需要灵活新增操作用访问者模式,需要解析特定语法(如表达式、规则)用解释器模式,两者可结合使用(如规则引擎中,通过解释器解析规则表达式,通过访问者模式执行规则校验操作)。

七、访问者模式的常见坑与避坑指南

坑1:数据结构频繁变化,导致访问者模式失效
访问者模式的前提是“数据结构固定”,如果数据结构频繁变化(如新增、删除元素类型),会导致需要修改抽象访问者和所有具体访问者的代码,违背开闭原则,让访问者模式失去意义。
避坑指南:仅在数据结构固定、元素类型不变的场景中使用访问者模式;若数据结构频繁变化,建议使用其他设计模式(如策略模式),或简化设计,不使用访问者模式。

坑2:元素类与访问者耦合过高
部分开发者在实现时,让元素类直接依赖具体访问者,或访问者直接访问元素类的私有成员,导致两者耦合过高,难以扩展和维护。
避坑指南:元素类仅依赖抽象访问者接口,不依赖具体访问者;访问者通过元素类的公共getter方法获取数据,不直接访问元素的私有成员;严格遵循“元素接受访问者,访问者操作元素”的逻辑,避免反向依赖。

坑3:过度使用访问者模式,导致逻辑复杂化
部分开发者在数据结构简单、操作较少的场景中,强行使用访问者模式,新增抽象访问者、具体访问者、对象结构等角色,导致代码冗余、逻辑复杂化,反而降低了代码的可读性和可维护性。
避坑指南:只有当数据结构固定、操作频繁变化,且新增操作需避免修改元素类时,才使用访问者模式;数据结构简单、操作较少的场景,直接在元素类中实现操作方法即可,无需过度设计。

坑4:忽略元素的遍历顺序,导致操作结果异常
对象结构的遍历顺序会影响访问者的操作结果(如计算总价时,遍历顺序不影响结果,但生成报表时,遍历顺序影响报表展示顺序),部分开发者忽略遍历顺序的控制,导致操作结果不符合预期。
避坑指南:在对象结构中明确遍历顺序(如按商品名称排序、按价格排序),确保访问者的操作结果符合业务预期;根据业务需求,提供可配置的遍历顺序,提升灵活性。

坑5:访问者职责过重,导致维护困难
部分开发者将多种不相关的操作逻辑封装在一个访问者类中,导致访问者职责过重,代码臃肿,难以维护和扩展。
避坑指南:遵循单一职责原则,一个具体访问者只负责一类相关操作(如计算相关操作、报表相关操作);新增操作时,新增对应的访问者类,避免一个访问者包含多种不相关逻辑。

八、系列文章预告

本篇文章,我们详细讲解了访问者模式的核心定义、五大核心角色、标准执行流程、电商商品列表操作实战代码、高频应用场景和避坑指南,同时区分了易混淆的解释器模式。访问者模式凭借“分离数据结构与操作、灵活扩展操作逻辑”的优势,成为数据结构固定、操作频繁变化场景的首选设计模式,能够大幅提升代码的可维护性和可扩展性,也是框架底层实现数据遍历与操作的核心思想之一。
下一篇,我们将学习行为型模式的第十七种常用模式——中介者模式,它的核心是定义一个中介对象,封装一系列对象之间的交互,使各对象不需要显式地相互引用,从而降低耦合度,并且可以独立地改变它们之间的交互。中介者模式专注于“解耦对象间的直接交互”,广泛应用于对象间交互复杂、耦合度高的场景,如聊天系统、订单系统、UI组件交互等。
中介者模式——封装对象交互,降低耦合度。我们不见不散!

Logo

电商企业物流数字化转型必备!快递鸟 API 接口,72 小时快速完成物流系统集成。全流程实战1V1指导,营造开放的API技术生态圈。

更多推荐