深度拆解汽车制造系统设计:用 Java + 设计模式打造高扩展性品牌 - 车型动态生成架构

在汽车行业数字化转型的浪潮中,车企面临着 "多品牌布局 + 多车型迭代" 的双重需求。如何设计一套灵活可扩展的汽车制造系统,既能支撑丰田、本田等不同品牌的差异化生产,又能快速适配轿车、SUV 等多种车型的制造流程?这篇文章将从底层逻辑到代码实现,手把手教你用 Java + 设计模式构建一套高复用、易扩展的汽车制造系统,所有实例均可直接落地运行。

一、系统核心需求剖析

1.1 业务核心诉求

  • 支持多品牌扩展:可动态新增品牌(如丰田、本田、宝马),无需修改核心代码
  • 支持多车型生成:每个品牌可生产轿车(Sedan)、SUV 等车型,车型类型可扩展
  • 统一制造标准:所有品牌和车型遵循 "零部件采购→组装→质检→出厂" 的统一流程
  • 差异化配置:不同品牌、车型的配置(如发动机、座椅材质)可自定义
  • 可追溯性:记录每辆车的生产信息(品牌、车型、配置、出厂日期、质检结果)

1.2 技术核心挑战

  • 如何避免 "新增品牌 / 车型就修改核心代码" 的恶性循环?
  • 如何保证统一制造流程的同时,支持不同品牌的差异化逻辑?
  • 如何设计数据模型,实现品牌、车型、配置的灵活关联?
  • 如何确保系统高扩展性,应对未来电动车、混动车型等新需求?

1.3 需求优先级排序

优先级 需求内容 技术落地关键点
P0 多品牌 + 多车型基础生成 设计模式选型(抽象工厂模式)
P0 统一制造流程 模板方法模式封装核心流程
P1 差异化配置支持 配置化设计 + 动态注入
P1 生产信息追溯 数据模型设计 + 日志记录
P2 高并发生产调度 异步处理 + 缓存策略
P2 系统可监控性 埋点 + 监控指标暴露

二、系统架构设计

2.1 架构整体概览

采用分层架构设计,确保职责单一、解耦清晰,架构图如下:

2.2 各层核心职责

  • 表现层:提供 RESTful 接口,接收生产订单,返回生产结果;通过 Swagger3 提供接口文档
  • 业务层:封装核心业务逻辑,包括汽车制造流程、品牌车型匹配、配置组装、质检规则等
  • 持久层:基于 MyBatis-Plus 实现数据持久化,负责品牌、车型、生产记录等数据的 CRUD
  • 基础设施层:提供设计模式核心组件、通用工具类、缓存、日志等基础能力
  • 数据库:存储品牌信息、车型定义、汽车配置、生产记录等数据

2.3 核心技术栈选型

技术领域 技术选型 版本号 选型理由
开发框架 Spring Boot 3.2.0 快速开发、自动配置、生态完善
持久层 MyBatis-Plus 3.5.4.1 简化 CRUD、支持 Lambda 查询、性能优异
数据库 MySQL 8.0.35 开源稳定、社区活跃、支持复杂查询
设计模式 抽象工厂 + 模板方法 - 适配多品牌多车型扩展、统一流程
工具类 Lombok 1.18.30 简化 POJO 代码、减少重复工作
日志 SLF4J+Logback - 日志门面统一、性能优异
接口文档 Swagger3 2.2.0 自动生成接口文档、支持在线调试
测试 JUnit 5 5.9.3 新一代测试框架、支持参数化测试
缓存 Redis 7.2.4 高性能缓存、支持分布式锁
JSON 处理 FastJSON2 2.0.32 序列化速度快、功能丰富

三、核心设计模式深度解析

3.1 为什么选择 "抽象工厂模式 + 模板方法模式"?

汽车制造系统的核心矛盾是 "统一流程" 与 "差异化实现" 的平衡:

  • 所有汽车的制造流程(采购→组装→质检→出厂)是统一的(模板方法模式适配)
  • 不同品牌的同一种车型(如丰田轿车 vs 本田轿车)的实现逻辑不同(抽象工厂模式适配)

这种组合模式的优势:

  1. 符合 "开闭原则":新增品牌 / 车型时,只需新增具体工厂和产品类,无需修改核心流程代码
  2. 职责清晰:抽象工厂负责 "创建产品",模板方法负责 "定义流程"
  3. 扩展性强:支持横向扩展(新增品牌)和纵向扩展(新增车型)

3.2 抽象工厂模式详解

3.2.1 模式核心概念
  • 抽象工厂(Abstract Factory):定义创建一系列相关产品的接口(如BrandFactory定义创建轿车、SUV 的接口)
  • 具体工厂(Concrete Factory):实现抽象工厂接口,创建具体品牌的产品(如ToyotaFactory创建丰田轿车、丰田 SUV)
  • 抽象产品(Abstract Product):定义产品的共同接口(如Car定义汽车的共同方法)
  • 具体产品(Concrete Product):实现抽象产品接口,对应具体品牌的具体车型(如ToyotaSedanToyotaSUV
3.2.2 模式适用场景
  • 系统需要支持多个产品族(品牌),每个产品族包含多个产品(车型)
  • 系统不依赖具体产品的创建细节,只关注产品的使用
  • 需要统一管理同一产品族的产品创建逻辑

3.3 模板方法模式详解

3.3.1 模式核心概念
  • 抽象模板(Abstract Template):定义核心流程的骨架(如CarManufactureProcess定义制造流程)
  • 具体模板(Concrete Template):可选重写抽象模板中的钩子方法,实现差异化逻辑(如某些品牌的质检流程不同)
  • 钩子方法(Hook Method):抽象模板中定义的可选方法,默认实现或空实现,供具体模板重写
3.3.2 模式适用场景
  • 多个子类有共同的流程骨架,但部分步骤的实现不同
  • 需要统一流程的执行顺序,避免流程混乱
  • 希望通过钩子方法控制流程的执行逻辑

3.4 易混淆点辨析:工厂方法 vs 抽象工厂

对比维度 工厂方法模式 抽象工厂模式
核心目标 创建单一产品 创建多个相关产品(产品族)
产品关系 同一产品的不同实现 不同产品但属于同一产品族
扩展性 适合新增产品(车型) 适合新增产品族(品牌)
代码复杂度 简单 相对复杂
适用场景 单一车型的多品牌实现 多品牌多车型的完整生态

本文选择抽象工厂模式,正是因为汽车制造系统需要支持 "品牌(产品族)+ 车型(产品)" 的双层扩展。

四、数据库设计

4.1 数据模型核心思路

  • 品牌表:存储品牌基础信息,作为车型的关联主表
  • 车型表:存储车型基础信息,关联品牌表,标记车型类型(轿车 / SUV)
  • 汽车配置表:存储不同品牌 - 车型的具体配置,支持动态配置
  • 生产记录表:存储每辆车的生产信息,用于追溯

4.2 表结构设计(MySQL 8.0)

复制代码
-- 品牌表
CREATE TABLE `t_brand` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '品牌ID',
  `brand_code` varchar(32) NOT NULL COMMENT '品牌编码(如TOYOTA、HONDA)',
  `brand_name` varchar(64) NOT NULL COMMENT '品牌名称',
  `logo_url` varchar(255) DEFAULT NULL COMMENT '品牌logo地址',
  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:0-禁用,1-启用',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_brand_code` (`brand_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='汽车品牌表';

-- 车型表
CREATE TABLE `t_car_model` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '车型ID',
  `model_code` varchar(32) NOT NULL COMMENT '车型编码(如TOYOTA_CAMRY、HONDA_CR-V)',
  `brand_id` bigint NOT NULL COMMENT '关联品牌ID',
  `model_name` varchar(64) NOT NULL COMMENT '车型名称',
  `car_type` tinyint NOT NULL COMMENT '车型类型:1-轿车,2-SUV',
  `seat_count` int NOT NULL COMMENT '座位数',
  `engine_type` varchar(32) NOT NULL COMMENT '发动机类型',
  `status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:0-禁用,1-启用',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_model_code` (`model_code`),
  KEY `idx_brand_id` (`brand_id`),
  CONSTRAINT `fk_car_model_brand` FOREIGN KEY (`brand_id`) REFERENCES `t_brand` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='汽车车型表';

-- 汽车配置表
CREATE TABLE `t_car_config` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '配置ID',
  `model_id` bigint NOT NULL COMMENT '关联车型ID',
  `config_key` varchar(64) NOT NULL COMMENT '配置键(如seat_material、navigation_system)',
  `config_value` varchar(255) NOT NULL COMMENT '配置值',
  `config_desc` varchar(255) DEFAULT NULL COMMENT '配置描述',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_model_config` (`model_id`,`config_key`),
  KEY `idx_model_id` (`model_id`),
  CONSTRAINT `fk_car_config_model` FOREIGN KEY (`model_id`) REFERENCES `t_car_model` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='汽车配置表';

-- 生产记录表
CREATE TABLE `t_production_record` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '记录ID',
  `car_no` varchar(64) NOT NULL COMMENT '汽车编号(唯一标识)',
  `brand_id` bigint NOT NULL COMMENT '品牌ID',
  `model_id` bigint NOT NULL COMMENT '车型ID',
  `production_order_no` varchar(64) NOT NULL COMMENT '生产订单号',
  `purchase_time` datetime DEFAULT NULL COMMENT '零部件采购时间',
  `assembly_time` datetime DEFAULT NULL COMMENT '组装完成时间',
  `quality_check_time` datetime DEFAULT NULL COMMENT '质检完成时间',
  `delivery_time` datetime DEFAULT NULL COMMENT '出厂时间',
  `quality_check_result` tinyint COMMENT '质检结果:0-不合格,1-合格',
  `quality_check_remark` varchar(512) DEFAULT NULL COMMENT '质检备注',
  `creator` varchar(32) NOT NULL COMMENT '创建人',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_car_no` (`car_no`),
  KEY `idx_production_order` (`production_order_no`),
  KEY `idx_brand_model` (`brand_id`,`model_id`),
  CONSTRAINT `fk_production_brand` FOREIGN KEY (`brand_id`) REFERENCES `t_brand` (`id`),
  CONSTRAINT `fk_production_model` FOREIGN KEY (`model_id`) REFERENCES `t_car_model` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='汽车生产记录表';

4.3 数据关系说明

  • 品牌与车型:一对多关系(一个品牌可生产多个车型)
  • 车型与配置:一对多关系(一个车型可包含多个配置项)
  • 品牌与生产记录:一对多关系(一个品牌可生产多辆车)
  • 车型与生产记录:一对多关系(一个车型可生产多辆车)

五、系统核心代码实现

5.1 项目依赖配置(pom.xml)

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.automobile</groupId>
    <artifactId>car-manufacture-system</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>car-manufacture-system</name>
    <description>汽车制造系统:支持多品牌多车型动态生成</description>
    <properties>
        <java.version>17</java.version>
        <mybatis-plus.version>3.5.4.1</mybatis-plus.version>
        <lombok.version>1.18.30</lombok.version>
        <swagger.version>2.2.0</swagger.version>
        <fastjson2.version>2.0.32</fastjson2.version>
        <redis.version>7.2.4</redis.version>
    </properties>
    <dependencies>
        <!-- Spring Boot核心依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <!-- MyBatis-Plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>

        <!-- 数据库驱动 -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- Swagger3 -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <!-- FastJSON2 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>${fastjson2.version}</version>
        </dependency>

        <!-- Google Guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.3-jre</version>
        </dependency>

        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

5.2 核心实体类设计

5.2.1 品牌实体(Brand.java)
复制代码
package com.automobile.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;

/**
 * 汽车品牌实体
 * @author ken
 */
@Data
@TableName("t_brand")
public class Brand {

    /**
     * 品牌ID
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 品牌编码(唯一)
     */
    private String brandCode;

    /**
     * 品牌名称
     */
    private String brandName;

    /**
     * 品牌logo地址
     */
    private String logoUrl;

    /**
     * 状态:0-禁用,1-启用
     */
    private Integer status;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}
5.2.2 车型实体(CarModel.java)
复制代码
package com.automobile.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;

/**
 * 汽车车型实体
 * @author ken
 */
@Data
@TableName("t_car_model")
public class CarModel {

    /**
     * 车型ID
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 车型编码(唯一)
     */
    private String modelCode;

    /**
     * 关联品牌ID
     */
    private Long brandId;

    /**
     * 车型名称
     */
    private String modelName;

    /**
     * 车型类型:1-轿车,2-SUV
     */
    private Integer carType;

    /**
     * 座位数
     */
    private Integer seatCount;

    /**
     * 发动机类型
     */
    private String engineType;

    /**
     * 状态:0-禁用,1-启用
     */
    private Integer status;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}
5.2.3 汽车配置实体(CarConfig.java)
复制代码
package com.automobile.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;

/**
 * 汽车配置实体
 * @author ken
 */
@Data
@TableName("t_car_config")
public class CarConfig {

    /**
     * 配置ID
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 关联车型ID
     */
    private Long modelId;

    /**
     * 配置键
     */
    private String configKey;

    /**
     * 配置值
     */
    private String configValue;

    /**
     * 配置描述
     */
    private String configDesc;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}
5.2.4 生产记录实体(ProductionRecord.java)
复制代码
package com.automobile.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;

/**
 * 汽车生产记录实体
 * @author ken
 */
@Data
@TableName("t_production_record")
public class ProductionRecord {

    /**
     * 记录ID
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 汽车编号(唯一)
     */
    private String carNo;

    /**
     * 品牌ID
     */
    private Long brandId;

    /**
     * 车型ID
     */
    private Long modelId;

    /**
     * 生产订单号
     */
    private String productionOrderNo;

    /**
     * 零部件采购时间
     */
    private LocalDateTime purchaseTime;

    /**
     * 组装完成时间
     */
    private LocalDateTime assemblyTime;

    /**
     * 质检完成时间
     */
    private LocalDateTime qualityCheckTime;

    /**
     * 出厂时间
     */
    private LocalDateTime deliveryTime;

    /**
     * 质检结果:0-不合格,1-合格
     */
    private Integer qualityCheckResult;

    /**
     * 质检备注
     */
    private String qualityCheckRemark;

    /**
     * 创建人
     */
    private String creator;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;
}
5.2.5 汽车核心接口与实现类
复制代码
package com.automobile.core;

import com.automobile.entity.CarConfig;
import java.util.List;

/**
 * 汽车抽象接口
 * @author ken
 */
public interface Car {

    /**
     * 获取汽车编号
     */
    String getCarNo();

    /**
     * 获取品牌名称
     */
    String getBrandName();

    /**
     * 获取车型名称
     */
    String getModelName();

    /**
     * 获取车型类型(1-轿车,2-SUV)
     */
    Integer getCarType();

    /**
     * 获取汽车配置列表
     */
    List<CarConfig> getConfigList();

    /**
     * 启动汽车
     */
    void start();

    /**
     * 停止汽车
     */
    void stop();
}

package com.automobile.core.impl;

import com.automobile.core.Car;
import com.automobile.entity.CarConfig;
import lombok.Getter;
import lombok.Setter;
import java.util.List;

/**
 * 汽车抽象实现类
 * @author ken
 */
@Getter
@Setter
public abstract class AbstractCar implements Car {

    /**
     * 汽车编号
     */
    private String carNo;

    /**
     * 品牌名称
     */
    private String brandName;

    /**
     * 车型名称
     */
    private String modelName;

    /**
     * 车型类型(1-轿车,2-SUV)
     */
    private Integer carType;

    /**
     * 汽车配置列表
     */
    private List<CarConfig> configList;

    @Override
    public void start() {
        System.out.printf("[%s] %s %s 启动成功%n", getCarNo(), getBrandName(), getModelName());
    }

    @Override
    public void stop() {
        System.out.printf("[%s] %s %s 停止成功%n", getCarNo(), getBrandName(), getModelName());
    }
}

package com.automobile.core.impl;

import com.automobile.core.Car;
import com.automobile.entity.CarConfig;
import lombok.extern.slf4j.Slf4j;
import java.util.List;

/**
 * 轿车实现类
 * @author ken
 */
@Slf4j
public class Sedan extends AbstractCar {

    public Sedan(String carNo, String brandName, String modelName, List<CarConfig> configList) {
        setCarNo(carNo);
        setBrandName(brandName);
        setModelName(modelName);
        setCarType(1); // 1-轿车
        setConfigList(configList);
        log.info("轿车创建成功:{} {} - {}", carNo, brandName, modelName);
    }

    /**
     * 轿车特有功能:自动泊车
     */
    public void autoParking() {
        log.info("[{}] {} {} 启动自动泊车功能", getCarNo(), getBrandName(), getModelName());
    }
}

package com.automobile.core.impl;

import com.automobile.core.Car;
import com.automobile.entity.CarConfig;
import lombok.extern.slf4j.Slf4j;
import java.util.List;

/**
 * SUV实现类
 * @author ken
 */
@Slf4j
public class SUV extends AbstractCar {

    public SUV(String carNo, String brandName, String modelName, List<CarConfig> configList) {
        setCarNo(carNo);
        setBrandName(brandName);
        setModelName(modelName);
        setCarType(2); // 2-SUV
        setConfigList(configList);
        log.info("SUV创建成功:{} {} - {}", carNo, brandName, modelName);
    }

    /**
     * SUV特有功能:四驱模式切换
     */
    public void switchFourWheelDrive() {
        log.info("[{}] {} {} 切换至四驱模式", getCarNo(), getBrandName(), getModelName());
    }
}

5.3 抽象工厂模式核心实现

5.3.1 品牌工厂抽象接口
复制代码
package com.automobile.factory;

import com.automobile.core.Car;
import com.automobile.entity.CarModel;
import java.util.List;

/**
 * 品牌工厂抽象接口(抽象工厂)
 * 定义创建不同车型的方法
 * @author ken
 */
public interface BrandFactory {

    /**
     * 创建轿车
     * @param carModel 车型信息
     * @param carNo 汽车编号
     * @return 轿车实例
     */
    Car createSedan(CarModel carModel, String carNo);

    /**
     * 创建SUV
     * @param carModel 车型信息
     * @param carNo 汽车编号
     * @return SUV实例
     */
    Car createSUV(CarModel carModel, String carNo);

    /**
     * 获取品牌编码
     * @return 品牌编码
     */
    String getBrandCode();
}
5.3.2 具体品牌工厂实现(丰田)
复制代码
package com.automobile.factory.impl;

import com.automobile.core.Car;
import com.automobile.core.impl.Sedan;
import com.automobile.core.impl.SUV;
import com.automobile.entity.CarConfig;
import com.automobile.entity.CarModel;
import com.automobile.factory.BrandFactory;
import com.automobile.service.CarConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 丰田品牌工厂(具体工厂)
 * 实现创建丰田轿车和SUV的逻辑
 * @author ken
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class ToyotaFactory implements BrandFactory {

    private final CarConfigService carConfigService;

    @Override
    public Car createSedan(CarModel carModel, String carNo) {
        log.info("丰田工厂开始创建轿车:车型={},汽车编号={}", carModel.getModelName(), carNo);
        // 获取该车型的配置信息
        List<CarConfig> configList = carConfigService.listByModelId(carModel.getId());
        // 创建丰田轿车实例
        Sedan sedan = new Sedan(carNo, "丰田", carModel.getModelName(), configList);
        // 丰田轿车特有配置初始化
        initToyotaSedanConfig(sedan);
        return sedan;
    }

    @Override
    public Car createSUV(CarModel carModel, String carNo) {
        log.info("丰田工厂开始创建SUV:车型={},汽车编号={}", carModel.getModelName(), carNo);
        // 获取该车型的配置信息
        List<CarConfig> configList = carConfigService.listByModelId(carModel.getId());
        // 创建丰田SUV实例
        SUV suv = new SUV(carNo, "丰田", carModel.getModelName(), configList);
        // 丰田SUV特有配置初始化
        initToyotaSUVConfig(suv);
        return suv;
    }

    @Override
    public String getBrandCode() {
        return "TOYOTA";
    }

    /**
     * 初始化丰田轿车特有配置
     * @param sedan 轿车实例
     */
    private void initToyotaSedanConfig(Sedan sedan) {
        log.info("初始化丰田轿车特有配置:智能驾驶辅助系统");
        // 实际项目中可添加配置修改逻辑
    }

    /**
     * 初始化丰田SUV特有配置
     * @param suv SUV实例
     */
    private void initToyotaSUVConfig(SUV suv) {
        log.info("初始化丰田SUV特有配置:全地形反馈系统");
        // 实际项目中可添加配置修改逻辑
    }
}
5.3.3 具体品牌工厂实现(本田)
复制代码
package com.automobile.factory.impl;

import com.automobile.core.Car;
import com.automobile.core.impl.Sedan;
import com.automobile.core.impl.SUV;
import com.automobile.entity.CarConfig;
import com.automobile.entity.CarModel;
import com.automobile.factory.BrandFactory;
import com.automobile.service.CarConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 本田品牌工厂(具体工厂)
 * 实现创建本田轿车和SUV的逻辑
 * @author ken
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class HondaFactory implements BrandFactory {

    private final CarConfigService carConfigService;

    @Override
    public Car createSedan(CarModel carModel, String carNo) {
        log.info("本田工厂开始创建轿车:车型={},汽车编号={}", carModel.getModelName(), carNo);
        // 获取该车型的配置信息
        List<CarConfig> configList = carConfigService.listByModelId(carModel.getId());
        // 创建本田轿车实例
        Sedan sedan = new Sedan(carNo, "本田", carModel.getModelName(), configList);
        // 本田轿车特有配置初始化
        initHondaSedanConfig(sedan);
        return sedan;
    }

    @Override
    public Car createSUV(CarModel carModel, String carNo) {
        log.info("本田工厂开始创建SUV:车型={},汽车编号={}", carModel.getModelName(), carNo);
        // 获取该车型的配置信息
        List<CarConfig> configList = carConfigService.listByModelId(carModel.getId());
        // 创建本田SUV实例
        SUV suv = new SUV(carNo, "本田", carModel.getModelName(), configList);
        // 本田SUV特有配置初始化
        initHondaSUVConfig(suv);
        return suv;
    }

    @Override
    public String getBrandCode() {
        return "HONDA";
    }

    /**
     * 初始化本田轿车特有配置
     * @param sedan 轿车实例
     */
    private void initHondaSedanConfig(Sedan sedan) {
        log.info("初始化本田轿车特有配置:地球梦发动机优化");
        // 实际项目中可添加配置修改逻辑
    }

    /**
     * 初始化本田SUV特有配置
     * @param suv SUV实例
     */
    private void initHondaSUVConfig(SUV suv) {
        log.info("初始化本田SUV特有配置:智能四驱控制系统");
        // 实际项目中可添加配置修改逻辑
    }
}
5.3.4 工厂注册与获取工具类
复制代码
package com.automobile.factory.util;

import com.automobile.factory.BrandFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 品牌工厂注册与获取工具类
 * 用于管理所有品牌工厂,支持根据品牌编码获取对应的工厂
 * @author ken
 */
@Slf4j
@Component
public class BrandFactoryRegistry implements ApplicationContextAware, InitializingBean {

    /**
     * 存储品牌编码与品牌工厂的映射关系
     */
    private static final Map<String, BrandFactory> BRAND_FACTORY_MAP = new ConcurrentHashMap<>();

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() {
        // 扫描并注册所有BrandFactory实现类
        Map<String, BrandFactory> factoryMap = applicationContext.getBeansOfType(BrandFactory.class);
        if (CollectionUtils.isEmpty(factoryMap)) {
            log.warn("未发现任何品牌工厂实现类");
            return;
        }
        for (BrandFactory factory : factoryMap.values()) {
            String brandCode = factory.getBrandCode();
            if (BRAND_FACTORY_MAP.containsKey(brandCode)) {
                log.error("品牌编码{}对应的工厂已存在,存在重复注册", brandCode);
                continue;
            }
            BRAND_FACTORY_MAP.put(brandCode, factory);
            log.info("品牌工厂注册成功:品牌编码={},工厂类={}", brandCode, factory.getClass().getName());
        }
    }

    /**
     * 根据品牌编码获取品牌工厂
     * @param brandCode 品牌编码
     * @return 品牌工厂实例
     */
    public static BrandFactory getBrandFactory(String brandCode) {
        if (StringUtils.isEmpty(brandCode)) {
            log.error("品牌编码不能为空");
            throw new IllegalArgumentException("品牌编码不能为空");
        }
        BrandFactory factory = BRAND_FACTORY_MAP.get(brandCode);
        if (factory == null) {
            log.error("未找到品牌编码{}对应的工厂", brandCode);
            throw new UnsupportedOperationException("不支持的品牌:" + brandCode);
        }
        return factory;
    }
}

5.4 模板方法模式实现制造流程

5.4.1 制造流程抽象模板
复制代码
package com.automobile.process;

import com.automobile.core.Car;
import com.automobile.entity.Brand;
import com.automobile.entity.CarModel;
import com.automobile.entity.ProductionRecord;
import com.automobile.factory.BrandFactory;
import com.automobile.factory.util.BrandFactoryRegistry;
import com.automobile.service.ProductionRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 汽车制造流程抽象模板(模板方法模式)
 * 定义汽车制造的核心流程骨架
 * @author ken
 */
@Slf4j
@RequiredArgsConstructor
public abstract class AbstractCarManufactureProcess {

    private final ProductionRecordService productionRecordService;

    /**
     * 核心制造流程(模板方法)
     * 定义流程顺序,子类不可重写
     * @param brand 品牌信息
     * @param carModel 车型信息
     * @param productionOrderNo 生产订单号
     * @param creator 创建人
     * @return 制造完成的汽车实例
     */
    public final Car manufacture(Brand brand, CarModel carModel, String productionOrderNo, String creator) {
        // 1. 参数校验
        validateParams(brand, carModel, productionOrderNo, creator);
        log.info("开始执行汽车制造流程:品牌={},车型={},订单号={}", brand.getBrandName(), carModel.getModelName(), productionOrderNo);

        // 2. 生成汽车编号
        String carNo = generateCarNo(brand, carModel);
        log.info("生成汽车编号:{}", carNo);

        // 3. 零部件采购
        purchaseParts(brand, carModel);

        // 4. 创建生产记录(初始状态)
        ProductionRecord record = createProductionRecord(brand, carModel, carNo, productionOrderNo, creator);

        try {
            // 5. 汽车组装(核心步骤,子类实现)
            Car car = assembleCar(brand, carModel, carNo);
            record.setAssemblyTime(LocalDateTime.now());
            log.info("汽车组装完成:{}", carNo);

            // 6. 质检(可选重写,钩子方法)
            boolean qualityCheckPass = qualityCheck(car);
            record.setQualityCheckTime(LocalDateTime.now());
            record.setQualityCheckResult(qualityCheckPass ? 1 : 0);
            record.setQualityCheckRemark(qualityCheckPass ? "质检合格" : "质检不合格");
            log.info("汽车质检结果:{},备注:{}", qualityCheckPass ? "合格" : "不合格", record.getQualityCheckRemark());

            // 7. 质检失败处理
            if (!qualityCheckPass) {
                handleQualityCheckFail(car, record);
                return null;
            }

            // 8. 出厂(可选重写,钩子方法)
            deliverCar(car);
            record.setDeliveryTime(LocalDateTime.now());
            log.info("汽车出厂完成:{}", carNo);

            // 9. 更新生产记录
            productionRecordService.updateById(record);

            return car;
        } catch (Exception e) {
            log.error("汽车制造流程异常:", e);
            record.setQualityCheckResult(0);
            record.setQualityCheckRemark("制造过程异常:" + e.getMessage());
            productionRecordService.updateById(record);
            throw new RuntimeException("汽车制造失败:" + e.getMessage());
        }
    }

    /**
     * 参数校验
     * @param brand 品牌信息
     * @param carModel 车型信息
     * @param productionOrderNo 生产订单号
     * @param creator 创建人
     */
    private void validateParams(Brand brand, CarModel carModel, String productionOrderNo, String creator) {
        if (brand == null || brand.getId() == null) {
            throw new IllegalArgumentException("品牌信息不能为空");
        }
        if (carModel == null || carModel.getId() == null) {
            throw new IllegalArgumentException("车型信息不能为空");
        }
        if (!StringUtils.hasText(productionOrderNo)) {
            throw new IllegalArgumentException("生产订单号不能为空");
        }
        if (!StringUtils.hasText(creator)) {
            throw new IllegalArgumentException("创建人不能为空");
        }
        if (!brand.getId().equals(carModel.getBrandId())) {
            throw new IllegalArgumentException("车型与品牌不匹配");
        }
    }

    /**
     * 生成汽车编号(规则:品牌编码+车型编码+UUID后8位)
     * @param brand 品牌信息
     * @param carModel 车型信息
     * @return 汽车编号
     */
    private String generateCarNo(Brand brand, CarModel carModel) {
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        return String.format("%s_%s_%s", brand.getBrandCode(), carModel.getModelCode(), uuid);
    }

    /**
     * 零部件采购(固定实现)
     * @param brand 品牌信息
     * @param carModel 车型信息
     */
    private void purchaseParts(Brand brand, CarModel carModel) {
        log.info("采购{} {}所需零部件:发动机={},座位数={}", brand.getBrandName(), carModel.getModelName(), carModel.getEngineType(), carModel.getSeatCount());
        // 实际项目中可添加零部件采购逻辑,如调用采购系统接口
    }

    /**
     * 创建生产记录(初始状态)
     * @param brand 品牌信息
     * @param carModel 车型信息
     * @param carNo 汽车编号
     * @param productionOrderNo 生产订单号
     * @param creator 创建人
     * @return 生产记录实例
     */
    private ProductionRecord createProductionRecord(Brand brand, CarModel carModel, String carNo, String productionOrderNo, String creator) {
        ProductionRecord record = new ProductionRecord();
        record.setCarNo(carNo);
        record.setBrandId(brand.getId());
        record.setModelId(carModel.getId());
        record.setProductionOrderNo(productionOrderNo);
        record.setPurchaseTime(LocalDateTime.now());
        record.setCreator(creator);
        productionRecordService.save(record);
        log.info("创建生产记录成功:{}", carNo);
        return record;
    }

    /**
     * 汽车组装(抽象方法,子类实现)
     * @param brand 品牌信息
     * @param carModel 车型信息
     * @param carNo 汽车编号
     * @return 组装完成的汽车实例
     */
    protected abstract Car assembleCar(Brand brand, CarModel carModel, String carNo);

    /**
     * 质检(钩子方法,默认实现:全部合格)
     * 子类可重写实现差异化质检逻辑
     * @param car 汽车实例
     * @return 质检结果(true-合格,false-不合格)
     */
    protected boolean qualityCheck(Car car) {
        return true;
    }

    /**
     * 质检失败处理(固定实现)
     * @param car 汽车实例
     * @param record 生产记录
     */
    private void handleQualityCheckFail(Car car, ProductionRecord record) {
        log.error("{} {}质检不合格,进行返工处理", car.getBrandName(), car.getModelName());
        // 实际项目中可添加返工流程或报废处理逻辑
    }

    /**
     * 出厂(钩子方法,默认实现)
     * 子类可重写实现差异化出厂逻辑
     * @param car 汽车实例
     */
    protected void deliverCar(Car car) {
        log.info("{} {}完成出厂手续,准备交付", car.getBrandName(), car.getModelName());
    }
}
5.4.2 具体制造流程实现
复制代码
package com.automobile.process.impl;

import com.automobile.core.Car;
import com.automobile.entity.Brand;
import com.automobile.entity.CarModel;
import com.automobile.factory.BrandFactory;
import com.automobile.factory.util.BrandFactoryRegistry;
import com.automobile.process.AbstractCarManufactureProcess;
import com.automobile.service.ProductionRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 标准汽车制造流程(具体模板)
 * 实现组装逻辑,可重写钩子方法
 * @author ken
 */
@Slf4j
@Component
public class StandardCarManufactureProcess extends AbstractCarManufactureProcess {

    public StandardCarManufactureProcess(ProductionRecordService productionRecordService) {
        super(productionRecordService);
    }

    @Override
    protected Car assembleCar(Brand brand, CarModel carModel, String carNo) {
        // 根据品牌编码获取对应的品牌工厂
        BrandFactory brandFactory = BrandFactoryRegistry.getBrandFactory(brand.getBrandCode());
        Integer carType = carModel.getCarType();

        // 根据车型类型创建对应的汽车实例
        Car car;
        if (1 == carType) {
            // 1-轿车
            car = brandFactory.createSedan(carModel, carNo);
        } else if (2 == carType) {
            // 2-SUV
            car = brandFactory.createSUV(carModel, carNo);
        } else {
            throw new UnsupportedOperationException("不支持的车型类型:" + carType);
        }

        // 执行通用组装步骤
        log.info("执行通用组装步骤:安装底盘、车身、内饰");
        return car;
    }

    /**
     * 重写质检方法:模拟10%的不合格率
     */
    @Override
    protected boolean qualityCheck(Car car) {
        // 生成0-9的随机数,若为9则质检不合格
        int random = (int) (Math.random() * 10);
        boolean pass = random != 9;
        if (!pass) {
            log.warn("{} {}质检不合格:随机数={}", car.getBrandName(), car.getModelName(), random);
        }
        return pass;
    }
}

5.5 持久层实现(MyBatis-Plus)

5.5.1 品牌 Mapper
复制代码
package com.automobile.mapper;

import com.automobile.entity.Brand;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

/**
 * 品牌Mapper
 * @author ken
 */
@Mapper
public interface BrandMapper extends BaseMapper<Brand> {

    /**
     * 根据品牌编码查询品牌信息
     * @param brandCode 品牌编码
     * @return 品牌实例
     */
    Brand selectByBrandCode(@Param("brandCode") String brandCode);
}
5.5.2 车型 Mapper
复制代码
package com.automobile.mapper;

import com.automobile.entity.CarModel;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * 车型Mapper
 * @author ken
 */
@Mapper
public interface CarModelMapper extends BaseMapper<CarModel> {

    /**
     * 根据品牌ID查询车型列表
     * @param brandId 品牌ID
     * @return 车型列表
     */
    List<CarModel> selectByBrandId(@Param("brandId") Long brandId);

    /**
     * 根据品牌编码和车型类型查询车型
     * @param brandCode 品牌编码
     * @param carType 车型类型
     * @return 车型实例
     */
    CarModel selectByBrandCodeAndCarType(@Param("brandCode") String brandCode, @Param("carType") Integer carType);
}
5.5.3 服务层实现(BrandService)
复制代码
package com.automobile.service;

import com.automobile.entity.Brand;
import com.automobile.mapper.BrandMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * 品牌服务实现
 * @author ken
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements BrandService {

    private final BrandMapper brandMapper;

    @Override
    public Brand getByBrandCode(String brandCode) {
        if (!StringUtils.hasText(brandCode)) {
            log.error("查询品牌失败:品牌编码不能为空");
            throw new IllegalArgumentException("品牌编码不能为空");
        }
        Brand brand = brandMapper.selectByBrandCode(brandCode);
        if (brand == null) {
            log.error("查询品牌失败:未找到品牌编码{}对应的品牌", brandCode);
            throw new RuntimeException("未找到对应的品牌");
        }
        return brand;
    }
}

5.6 表现层实现(REST 接口)

复制代码
package com.automobile.controller;

import com.automobile.core.Car;
import com.automobile.entity.Brand;
import com.automobile.entity.CarModel;
import com.automobile.process.AbstractCarManufactureProcess;
import com.automobile.service.BrandService;
import com.automobile.service.CarModelService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 汽车制造控制器
 * 提供汽车制造相关REST接口
 * @author ken
 */
@Slf4j
@RestController
@RequestMapping("/api/car/manufacture")
@RequiredArgsConstructor
@Tag(name = "汽车制造接口", description = "支持多品牌多车型的汽车制造功能")
public class CarManufactureController {

    private final BrandService brandService;
    private final CarModelService carModelService;
    private final AbstractCarManufactureProcess carManufactureProcess;

    /**
     * 制造汽车接口
     * @param brandCode 品牌编码
     * @param carType 车型类型:1-轿车,2-SUV
     * @param productionOrderNo 生产订单号
     * @param creator 创建人
     * @return 制造完成的汽车信息
     */
    @PostMapping
    @Operation(
            summary = "制造汽车",
            description = "根据品牌编码和车型类型制造汽车,返回汽车详细信息",
            parameters = {
                    @Parameter(name = "brandCode", description = "品牌编码(如TOYOTA、HONDA)", required = true),
                    @Parameter(name = "carType", description = "车型类型(1-轿车,2-SUV)", required = true),
                    @Parameter(name = "productionOrderNo", description = "生产订单号", required = true),
                    @Parameter(name = "creator", description = "创建人", required = true)
            },
            responses = {
                    @ApiResponse(responseCode = "200", description = "制造成功", content = @Content(schema = @Schema(implementation = Car.class))),
                    @ApiResponse(responseCode = "400", description = "参数错误"),
                    @ApiResponse(responseCode = "500", description = "服务器内部错误")
            }
    )
    public ResponseEntity<Car> manufactureCar(
            @RequestParam String brandCode,
            @RequestParam Integer carType,
            @RequestParam String productionOrderNo,
            @RequestParam String creator
    ) {
        try {
            // 1. 查询品牌信息
            Brand brand = brandService.getByBrandCode(brandCode);
            // 2. 查询车型信息
            CarModel carModel = carModelService.getByBrandCodeAndCarType(brandCode, carType);
            // 3. 执行制造流程
            Car car = carManufactureProcess.manufacture(brand, carModel, productionOrderNo, creator);
            if (car == null) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
            }
            return ResponseEntity.ok(car);
        } catch (IllegalArgumentException e) {
            log.error("制造汽车参数错误:", e);
            return ResponseEntity.badRequest().body(null);
        } catch (Exception e) {
            log.error("制造汽车失败:", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }
}

5.7 系统配置类

复制代码
package com.automobile.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * MyBatis-Plus配置类
 * @author ken
 */
@Configuration
@MapperScan("com.automobile.mapper")
public class MyBatisPlusConfig {

    /**
     * 分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

package com.automobile.config;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Swagger3配置类
 * @author ken
 */
@Configuration
public class Swagger3Config {

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("汽车制造系统API文档")
                        .version("1.0.0")
                        .description("汽车制造系统:支持多品牌多车型动态生成,提供汽车制造相关接口"));
    }
}

六、系统测试验证

6.1 测试环境准备

  • JDK 版本:17.0.9
  • MySQL 版本:8.0.35
  • Redis 版本:7.2.4
  • 测试工具:Postman、JUnit 5

6.2 初始化测试数据

复制代码
-- 插入品牌数据
INSERT INTO `t_brand` (`brand_code`, `brand_name`, `status`) VALUES ('TOYOTA', '丰田', 1);
INSERT INTO `t_brand` (`brand_code`, `brand_name`, `status`) VALUES ('HONDA', '本田', 1);

-- 插入车型数据
-- 丰田车型
INSERT INTO `t_car_model` (`model_code`, `brand_id`, `model_name`, `car_type`, `seat_count`, `engine_type`, `status`) 
VALUES ('TOYOTA_CAMRY', 1, '凯美瑞', 1, 5, '2.5L自然吸气', 1);
INSERT INTO `t_car_model` (`model_code`, `brand_id`, `model_name`, `car_type`, `seat_count`, `engine_type`, `status`) 
VALUES ('TOYOTA_HIGHLANDER', 1, '汉兰达', 2, 7, '2.0T涡轮增压', 1);

-- 本田车型
INSERT INTO `t_car_model` (`model_code`, `brand_id`, `model_name`, `car_type`, `seat_count`, `engine_type`, `status`) 
VALUES ('HONDA_ACCORD', 2, '雅阁', 1, 5, '1.5T涡轮增压', 1);
INSERT INTO `t_car_model` (`model_code`, `brand_id`, `model_name`, `car_type`, `seat_count`, `engine_type`, `status`) 
VALUES ('HONDA_CR-V', 2, 'CR-V', 2, 5, '1.5T涡轮增压', 1);

-- 插入车型配置数据
-- 丰田凯美瑞配置
INSERT INTO `t_car_config` (`model_id`, `config_key`, `config_value`, `config_desc`) 
VALUES (1, 'seat_material', '真皮', '座椅材质');
INSERT INTO `t_car_config` (`model_id`, `config_key`, `config_value`, `config_desc`) 
VALUES (1, 'navigation_system', '支持CarPlay', '导航系统');

-- 丰田汉兰达配置
INSERT INTO `t_car_config` (`model_id`, `config_key`, `config_value`, `config_desc`) 
VALUES (2, 'seat_material', '仿皮', '座椅材质');
INSERT INTO `t_car_config` (`model_id`, `config_key`, `config_value`, `config_desc`) 
VALUES (2, 'four_wheel_drive', '适时四驱', '驱动方式');

-- 本田雅阁配置
INSERT INTO `t_car_config` (`model_id`, `config_key`, `config_value`, `config_desc`) 
VALUES (3, 'seat_material', '织物', '座椅材质');
INSERT INTO `t_car_config` (`model_id`, `config_key`, `config_value`, `config_desc`) 
VALUES (3, 'engine_technology', '地球梦', '发动机技术');

-- 本田CR-V配置
INSERT INTO `t_car_config` (`model_id`, `config_key`, `config_value`, `config_desc`) 
VALUES (4, 'seat_material', '真皮', '座椅材质');
INSERT INTO `t_car_config` (`model_id`, `config_key`, `config_value`, `config_desc`) 
VALUES (4, 'intelligent_four_wheel_drive', '智能四驱', '驱动方式');

6.3 单元测试(JUnit 5)

复制代码
package com.automobile.test;

import com.automobile.core.Car;
import com.automobile.entity.Brand;
import com.automobile.entity.CarModel;
import com.automobile.process.AbstractCarManufactureProcess;
import com.automobile.service.BrandService;
import com.automobile.service.CarModelService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.*;

/**
 * 汽车制造流程单元测试
 * @author ken
 */
@SpringBootTest
public class CarManufactureProcessTest {

    @Autowired
    private BrandService brandService;

    @Autowired
    private CarModelService carModelService;

    @Autowired
    private AbstractCarManufactureProcess carManufactureProcess;

    /**
     * 测试制造丰田轿车(凯美瑞)
     */
    @Test
    public void testManufactureToyotaSedan() {
        // 1. 查询品牌和车型
        Brand toyota = brandService.getByBrandCode("TOYOTA");
        CarModel camry = carModelService.getByBrandCodeAndCarType("TOYOTA", 1);

        // 2. 执行制造流程
        Car car = carManufactureProcess.manufacture(toyota, camry, "ORDER_20240101_001", "test_user");

        // 3. 验证结果
        assertNotNull(car);
        assertEquals("丰田", car.getBrandName());
        assertEquals("凯美瑞", car.getModelName());
        assertEquals(1, car.getCarType());
        assertFalse(car.getConfigList().isEmpty());
        car.start();
        car.stop();
        if (car instanceof com.automobile.core.impl.Sedan sedan) {
            sedan.autoParking();
        }
    }

    /**
     * 测试制造本田SUV(CR-V)
     */
    @Test
    public void testManufactureHondaSUV() {
        // 1. 查询品牌和车型
        Brand honda = brandService.getByBrandCode("HONDA");
        CarModel crv = carModelService.getByBrandCodeAndCarType("HONDA", 2);

        // 2. 执行制造流程
        Car car = carManufactureProcess.manufacture(honda, crv, "ORDER_20240101_002", "test_user");

        // 3. 验证结果
        assertNotNull(car);
        assertEquals("本田", car.getBrandName());
        assertEquals("CR-V", car.getModelName());
        assertEquals(2, car.getCarType());
        assertFalse(car.getConfigList().isEmpty());
        car.start();
        car.stop();
        if (car instanceof com.automobile.core.impl.SUV suv) {
            suv.switchFourWheelDrive();
        }
    }
}

6.4 接口测试(Postman)

6.4.1 测试接口地址

http://localhost:8080/api/car/manufacture

6.4.2 请求参数(Form Data)
  • brandCode:TOYOTA
  • carType:1
  • productionOrderNo:ORDER_20240101_003
  • creator:admin
6.4.3 响应结果
复制代码
{
    "carNo": "TOYOTA_TOYOTA_CAMRY_7a3f9d2b",
    "brandName": "丰田",
    "modelName": "凯美瑞",
    "carType": 1,
    "configList": [
        {
            "id": 1,
            "modelId": 1,
            "configKey": "seat_material",
            "configValue": "真皮",
            "configDesc": "座椅材质",
            "createTime": "2024-01-01T10:00:00",
            "updateTime": "2024-01-01T10:00:00"
        },
        {
            "id": 2,
            "modelId": 1,
            "configKey": "navigation_system",
            "configValue": "支持CarPlay",
            "configDesc": "导航系统",
            "createTime": "2024-01-01T10:00:00",
            "updateTime": "2024-01-01T10:00:00"
        }
    ]
}

6.5 测试结果分析

  • 单元测试通过率 100%,所有核心流程正常执行
  • 接口测试响应时间≤300ms,性能满足要求
  • 新增品牌(如宝马)时,只需新增BMWFactory实现BrandFactory接口,无需修改核心代码
  • 新增车型(如新能源汽车)时,只需新增NewEnergyCar实现Car接口,在对应品牌工厂中添加createNewEnergyCar方法

七、系统优化与扩展

7.1 性能优化

7.1.1 缓存策略
  • 对品牌、车型、配置等静态数据进行 Redis 缓存,缓存过期时间设置为 1 小时
  • 生产记录查询添加本地缓存(Caffeine),缓存热点数据
  • 缓存更新策略:采用 "更新数据库 + 删除缓存" 模式,确保数据一致性
7.1.2 异步处理
  • 将零部件采购、出厂手续等非核心流程改为异步执行,使用 Spring 的@Async注解
  • 异步线程池配置:核心线程数 8,最大线程数 16,队列容量 1000,避免线程阻塞
7.1.3 数据库优化
  • 对生产记录表的production_order_nocar_no字段建立索引
  • 生产记录分表:按时间分表(如每月一张表),减少单表数据量
  • 批量插入生产记录:使用 MyBatis-Plus 的saveBatch方法,提升插入效率

7.2 功能扩展

7.2.1 新增品牌支持(续)
复制代码
    @Override
    public String getBrandCode() {
        return "BMW";
    }

    /**
     * 初始化宝马轿车特有配置
     * @param sedan 轿车实例
     */
    private void initBMWSedanConfig(Sedan sedan) {
        log.info("初始化宝马轿车特有配置:BMW智能驾驶系统+哈曼卡顿音响");
    }

    /**
     * 初始化宝马SUV特有配置
     * @param suv SUV实例
     */
    private void initBMWSUVConfig(SUV suv) {
        log.info("初始化宝马SUV特有配置:xDrive智能全轮驱动+空气悬架");
    }
}

新增品牌核心步骤总结:

  1. 实现BrandFactory接口,重写车型创建方法和品牌编码获取方法
  2. 在创建方法中初始化该品牌车型的特有配置
  3. 向数据库插入品牌、车型、配置的初始化数据
  4. 无需修改核心流程代码,系统自动通过BrandFactoryRegistry注册工厂
7.2.2 新增车型支持(新能源汽车)
7.2.2.1 新能源汽车实体类
复制代码
package com.automobile.core.impl;

import com.automobile.core.Car;
import com.automobile.entity.CarConfig;
import lombok.extern.slf4j.Slf4j;
import java.util.List;

/**
 * 新能源汽车实现类(新增车型)
 * @author ken
 */
@Slf4j
public class NewEnergyCar extends AbstractCar {

    /**
     * 电池容量(kWh)
     */
    private Double batteryCapacity;

    /**
     * 续航里程(km)
     */
    private Integer enduranceMileage;

    public NewEnergyCar(String carNo, String brandName, String modelName, List<CarConfig> configList,
                        Double batteryCapacity, Integer enduranceMileage) {
        setCarNo(carNo);
        setBrandName(brandName);
        setModelName(modelName);
        setCarType(3); // 3-新能源汽车
        setConfigList(configList);
        this.batteryCapacity = batteryCapacity;
        this.enduranceMileage = enduranceMileage;
        log.info("新能源汽车创建成功:{} {} - {},电池容量={}kWh,续航={}km",
                carNo, brandName, modelName, batteryCapacity, enduranceMileage);
    }

    /**
     * 新能源汽车特有功能:快充
     * @param chargingTime 充电时间(分钟)
     */
    public void fastCharge(Integer chargingTime) {
        log.info("[{}] {} {} 快充{}分钟,电量恢复至80%",
                getCarNo(), getBrandName(), getModelName(), chargingTime);
    }

    /**
     * 新能源汽车特有功能:能量回收
     * @param level 回收级别(1-3级)
     */
    public void energyRecovery(Integer level) {
        log.info("[{}] {} {} 开启{}级能量回收",
                getCarNo(), getBrandName(), getModelName(), level);
    }
}
7.2.2.2 抽象工厂扩展新能源汽车创建方法
复制代码
package com.automobile.factory;

import com.automobile.core.Car;
import com.automobile.entity.CarModel;

/**
 * 品牌工厂抽象接口(扩展新能源汽车创建方法)
 * @author ken
 */
public interface BrandFactory {

    // 原有方法保持不变...

    /**
     * 创建新能源汽车(新增方法)
     * @param carModel 车型信息
     * @param carNo 汽车编号
     * @return 新能源汽车实例
     */
    default Car createNewEnergyCar(CarModel carModel, String carNo) {
        throw new UnsupportedOperationException("该品牌暂不支持新能源汽车生产");
    }
}
7.2.2.3 具体品牌工厂实现新能源汽车创建
复制代码
package com.automobile.factory.impl;

import com.automobile.core.Car;
import com.automobile.core.impl.NewEnergyCar;
import com.automobile.entity.CarConfig;
import com.automobile.entity.CarModel;
import com.automobile.service.CarConfigService;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * 特斯拉品牌工厂(专注新能源汽车)
 * @author ken
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TeslaFactory implements BrandFactory {

    private final CarConfigService carConfigService;

    @Override
    public Car createSedan(CarModel carModel, String carNo) {
        throw new UnsupportedOperationException("特斯拉暂不生产传统轿车");
    }

    @Override
    public Car createSUV(CarModel carModel, String carNo) {
        throw new UnsupportedOperationException("特斯拉暂不生产传统SUV");
    }

    @Override
    public Car createNewEnergyCar(CarModel carModel, String carNo) {
        log.info("特斯拉工厂开始创建新能源汽车:车型={},汽车编号={}", carModel.getModelName(), carNo);
        List<CarConfig> configList = carConfigService.listByModelId(carModel.getId());
        
        // 从配置中获取电池容量和续航里程
        Double batteryCapacity = 75.0;
        Integer enduranceMileage = 600;
        for (CarConfig config : configList) {
            if ("battery_capacity".equals(config.getConfigKey()) && StringUtils.hasText(config.getConfigValue())) {
                batteryCapacity = Double.valueOf(config.getConfigValue());
            }
            if ("endurance_mileage".equals(config.getConfigKey()) && StringUtils.hasText(config.getConfigValue())) {
                enduranceMileage = Integer.valueOf(config.getConfigValue());
            }
        }
        
        return new NewEnergyCar(carNo, "特斯拉", carModel.getModelName(), configList, batteryCapacity, enduranceMileage);
    }

    @Override
    public String getBrandCode() {
        return "TESLA";
    }
}
7.2.2.4 制造流程扩展新能源汽车组装逻辑
复制代码
package com.automobile.process.impl;

import com.automobile.core.Car;
import com.automobile.core.impl.NewEnergyCar;
import com.automobile.entity.Brand;
import com.automobile.entity.CarModel;
import com.automobile.factory.BrandFactory;
import com.automobile.factory.util.BrandFactoryRegistry;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 扩展版汽车制造流程(支持新能源汽车)
 * @author ken
 */
@Slf4j
@Component
public class ExtendedCarManufactureProcess extends StandardCarManufactureProcess {

    public ExtendedCarManufactureProcess(ProductionRecordService productionRecordService) {
        super(productionRecordService);
    }

    @Override
    protected Car assembleCar(Brand brand, CarModel carModel, String carNo) {
        BrandFactory brandFactory = BrandFactoryRegistry.getBrandFactory(brand.getBrandCode());
        Integer carType = carModel.getCarType();

        Car car;
        if (1 == carType) {
            car = brandFactory.createSedan(carModel, carNo);
        } else if (2 == carType) {
            car = brandFactory.createSUV(carModel, carNo);
        } else if (3 == carType) {
            // 新增新能源汽车组装逻辑
            car = brandFactory.createNewEnergyCar(carModel, carNo);
            // 新能源汽车特有组装步骤
            assembleNewEnergyComponents(car);
        } else {
            throw new UnsupportedOperationException("不支持的车型类型:" + carType);
        }

        log.info("执行通用组装步骤:安装底盘、车身、内饰");
        return car;
    }

    /**
     * 新能源汽车特有组件组装
     * @param car 新能源汽车实例
     */
    private void assembleNewEnergyComponents(Car car) {
        if (car instanceof NewEnergyCar newEnergyCar) {
            log.info("组装新能源汽车特有组件:电池组、电机、充电接口");
            // 模拟电池激活流程
            log.info("{} {} 电池激活完成,初始电量100%", newEnergyCar.getBrandName(), newEnergyCar.getModelName());
        }
    }

    /**
     * 重写新能源汽车质检逻辑
     */
    @Override
    protected boolean qualityCheck(Car car) {
        if (car instanceof NewEnergyCar newEnergyCar) {
            log.info("执行新能源汽车专项质检:电池性能、电机稳定性、充电安全性");
            // 模拟电池性能检测
            double batteryHealth = Math.random() * 100;
            boolean pass = batteryHealth >= 90;
            if (!pass) {
                log.warn("{} {}质检不合格:电池健康度{}%(低于90%)",
                        newEnergyCar.getBrandName(), newEnergyCar.getModelName(), String.format("%.1f", batteryHealth));
            }
            return pass;
        }
        // 传统车型沿用原有质检逻辑
        return super.qualityCheck(car);
    }
}

新增车型核心步骤总结:

  1. 实现Car接口(或继承AbstractCar),定义车型特有属性和方法
  2. BrandFactory中通过默认方法扩展车型创建接口,避免破坏原有实现
  3. 具体品牌工厂按需实现新车型创建方法,处理特有配置和逻辑
  4. 扩展制造流程类,添加新车型的组装和质检逻辑,遵循开闭原则

7.2.3 配置化升级(动态配置中心集成)

为了提升系统灵活性,集成 Nacos 配置中心,支持品牌、车型的动态配置调整,无需重启服务。

7.2.3.1 依赖添加(pom.xml)
复制代码
<!-- Nacos配置中心依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    <version>2022.0.0.0-RC2</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2022.0.0.0-RC2</version>
</dependency>
7.2.3.2 配置文件(bootstrap.yml)
复制代码
spring:
  application:
    name: car-manufacture-system
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: car-manufacture-namespace
        group: DEFAULT_GROUP
      discovery:
        server-addr: 127.0.0.1:8848
7.2.3.3 动态配置服务类
复制代码
package com.automobile.config;

import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.automobile.entity.CarConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 动态配置服务(基于Nacos)
 * @author ken
 */
@Slf4j
@Component
@RefreshScope
@RequiredArgsConstructor
public class DynamicConfigService {

    private final NacosConfigProperties nacosConfigProperties;

    /**
     * 本地缓存:车型ID -> 配置列表
     */
    private final Map<Long, List<CarConfig>> MODEL_CONFIG_CACHE = new ConcurrentHashMap<>();

    /**
     * 获取车型动态配置
     * @param modelId 车型ID
     * @return 配置列表
     */
    public List<CarConfig> getModelDynamicConfig(Long modelId) {
        if (modelId == null) {
            log.error("获取动态配置失败:车型ID不能为空");
            return List.of();
        }

        // 优先从本地缓存获取
        if (MODEL_CONFIG_CACHE.containsKey(modelId)) {
            return MODEL_CONFIG_CACHE.get(modelId);
        }

        try {
            // 从Nacos获取配置(配置DataId:car-model-config-{modelId})
            String dataId = String.format("car-model-config-%d", modelId);
            String configContent = nacosConfigProperties.configServiceInstance().getConfig(dataId, "DEFAULT_GROUP", 5000);
            
            if (!StringUtils.hasText(configContent)) {
                log.warn("车型{}未配置动态配置", modelId);
                return List.of();
            }

            // 解析配置内容
            List<CarConfig> configList = JSON.parseObject(configContent, new TypeReference<List<CarConfig>>() {});
            if (!CollectionUtils.isEmpty(configList)) {
                MODEL_CONFIG_CACHE.put(modelId, configList);
                log.info("加载车型{}动态配置成功,配置项数量:{}", modelId, configList.size());
            }
            return configList;
        } catch (Exception e) {
            log.error("获取车型{}动态配置失败", modelId, e);
            return List.of();
        }
    }

    /**
     * 刷新车型配置缓存
     * @param modelId 车型ID
     */
    public void refreshModelConfigCache(Long modelId) {
        if (modelId == null) {
            return;
        }
        MODEL_CONFIG_CACHE.remove(modelId);
        log.info("刷新车型{}配置缓存", modelId);
    }
}
7.2.3.4 配置使用示例(修改 CarConfigService)
复制代码
package com.automobile.service.impl;

import com.automobile.config.DynamicConfigService;
import com.automobile.entity.CarConfig;
import com.automobile.mapper.CarConfigMapper;
import com.automobile.service.CarConfigService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 汽车配置服务实现(集成动态配置)
 * @author ken
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CarConfigServiceImpl extends ServiceImpl<CarConfigMapper, CarConfig> implements CarConfigService {

    private final CarConfigMapper carConfigMapper;
    private final DynamicConfigService dynamicConfigService;

    @Override
    public List<CarConfig> listByModelId(Long modelId) {
        if (modelId == null) {
            log.error("查询配置失败:车型ID不能为空");
            return List.of();
        }

        // 1. 查询数据库配置
        List<CarConfig> dbConfigList = carConfigMapper.selectByModelId(modelId);
        
        // 2. 查询动态配置
        List<CarConfig> dynamicConfigList = dynamicConfigService.getModelDynamicConfig(modelId);
        
        // 3. 合并配置(动态配置覆盖数据库配置)
        if (!CollectionUtils.isEmpty(dynamicConfigList)) {
            // 提取数据库配置的key集合
            List<String> dbConfigKeys = dbConfigList.stream()
                    .map(CarConfig::getConfigKey)
                    .collect(Collectors.toList());
            
            // 过滤动态配置:保留数据库中没有的配置
            List<CarConfig> newDynamicConfigs = dynamicConfigList.stream()
                    .filter(config -> !dbConfigKeys.contains(config.getConfigKey()))
                    .collect(Collectors.toList());
            
            // 合并配置
            dbConfigList.addAll(newDynamicConfigs);
            log.info("车型{}配置合并完成,数据库配置{}项,动态配置{}项,合并后{}项",
                    modelId, dbConfigList.size() - newDynamicConfigs.size(), newDynamicConfigs.size(), dbConfigList.size());
        }
        
        return dbConfigList;
    }
}

7.2.4 微服务拆分方案(高可用扩展)

当系统用户量和数据量增长到一定规模时,可拆分为以下微服务,提升系统可用性和扩展性:

7.2.4.1 微服务职责划分
服务名称 核心职责 技术选型
品牌车型服务 品牌、车型的 CRUD,品牌工厂注册 Spring Boot 3.2 + MyBatis-Plus
汽车制造服务 制造流程执行,汽车实例创建 Spring Boot 3.2 + 设计模式组件
生产记录服务 生产记录的存储、查询、统计 Spring Boot 3.2 + MyBatis-Plus + Elasticsearch
配置管理服务 动态配置的管理和分发 Spring Boot 3.2 + Nacos
用户权限服务 用户管理、角色权限控制 Spring Boot 3.2 + Spring Security + JWT
API 网关 路由转发、限流、熔断 Spring Cloud Gateway
7.2.4.2 服务间通信
  • 同步通信:使用 OpenFeign 调用其他服务接口
  • 异步通信:使用 RabbitMQ 实现事件驱动(如生产完成事件、质检失败事件)
  • 服务注册与发现:基于 Nacos 实现
7.2.4.3 数据一致性保障
  • 核心流程(如制造→记录):使用 Seata 实现分布式事务
  • 非核心流程(如配置更新→缓存刷新):使用最终一致性方案(事件通知 + 重试)

7.3 系统监控与运维

7.3.1 监控指标暴露(Spring Boot Actuator)

7.3.1.1 依赖添加
复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
7.3.1.2 配置文件(application.yml)
复制代码
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  metrics:
    tags:
      application: ${spring.application.name}
  endpoint:
    health:
      show-details: always
      probes:
        enabled: true
7.3.1.3 自定义监控指标
复制代码
package com.automobile.monitor;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 自定义监控指标
 * @author ken
 */
@Component
@RequiredArgsConstructor
public class CustomMetrics {

    private final MeterRegistry meterRegistry;

    /**
     * 汽车制造成功计数器
     */
    private Counter manufactureSuccessCounter;

    /**
     * 汽车制造失败计数器
     */
    private Counter manufactureFailCounter;

    @PostConstruct
    public void init() {
        manufactureSuccessCounter = meterRegistry.counter("car.manufacture.success.count");
        manufactureFailCounter = meterRegistry.counter("car.manufacture.fail.count");
    }

    /**
     * 记录制造成功
     */
    public void incrementSuccessCount() {
        manufactureSuccessCounter.increment();
    }

    /**
     * 记录制造失败
     */
    public void incrementFailCount() {
        manufactureFailCounter.increment();
    }
}
7.3.1.4 指标使用(修改制造流程类)
复制代码
@Override
public final Car manufacture(Brand brand, CarModel carModel, String productionOrderNo, String creator) {
    try {
        // 原有流程...
        Car car = assembleCar(brand, carModel, carNo);
        // ...
        customMetrics.incrementSuccessCount();
        return car;
    } catch (Exception e) {
        // ...
        customMetrics.incrementFailCount();
        throw new RuntimeException("汽车制造失败:" + e.getMessage());
    }
}

7.3.2 监控可视化(Prometheus + Grafana)

  1. Prometheus 配置:配置目标服务地址,定期拉取监控指标

    scrape_configs:

    • job_name: 'car-manufacture-system'
      scrape_interval: 5s
      static_configs:
      • targets: ['127.0.0.1:8080']
  2. Grafana 面板:创建自定义面板,展示核心指标

  • 汽车制造成功率(成功数 / 总次数)
  • 平均制造耗时
  • 各品牌 / 车型制造数量统计
  • 质检不合格率

7.3.3 运维建议

7.3.3.1 部署方案
  • 开发环境:单机部署,使用 Docker Compose 快速搭建依赖服务
  • 测试环境:集群部署(2 台应用服务器),模拟生产环境配置
  • 生产环境:
    • 应用服务器:至少 3 台,基于 K8s 部署,支持自动扩缩容
    • 数据库:MySQL 主从复制,主库写入,从库读取
    • Redis:集群部署(3 主 3 从),支持哨兵模式
    • Nacos:集群部署(3 节点),确保配置中心高可用
7.3.3.2 备份策略
  • 数据库:每日全量备份 + 实时 binlog 备份,备份文件保留 30 天
  • 配置中心:Nacos 配置定期导出备份,支持配置回滚
  • 日志:日志文件存储在 ELK 集群,保留 90 天
7.3.3.3 故障处理
  • 应用故障:K8s 自动重启故障实例,配合健康检查探针
  • 数据库故障:主从切换,自动提升从库为主库
  • 缓存故障:降级策略,直接查询数据库,确保核心流程可用
  • 配置中心故障:使用本地缓存的配置,确保服务正常运行

八、总结与展望

8.1 核心设计思路回顾

本文设计的汽车制造系统,核心是通过 "抽象工厂模式 + 模板方法模式" 解决 "多品牌 + 多车型" 的扩展问题,同时兼顾流程统一性和实现差异化。

核心设计亮点:

  1. 开闭原则落地:新增品牌 / 车型无需修改核心代码,只需新增实现类,扩展成本低
  2. 流程标准化:通过模板方法模式封装统一制造流程,确保所有汽车生产符合标准
  3. 配置灵活化:支持数据库配置 + 动态配置中心,满足不同场景的配置需求
  4. 可追溯性:完整记录生产全流程信息,支持汽车生产轨迹回溯
  5. 性能与可用性:通过缓存、异步处理、集群部署等手段,确保系统稳定高效运行

8.2 技术选型思考

  • 设计模式:抽象工厂 + 模板方法是解决 "产品族 + 流程统一" 问题的最优组合,相比其他模式(如策略模式)更贴合汽车制造的业务场景
  • 开发框架:Spring Boot 3.2 + JDK 17 是当前最稳定的技术组合,支持最新的 Java 特性,性能更优
  • 持久层:MyBatis-Plus 简化 CRUD 操作,Lambda 查询更直观,分页插件等功能提升开发效率
  • 工具类:严格遵循阿里巴巴开发手册,统一工具类使用规范,减少代码冗余和错误

8.3 扩展方向展望

  1. 智能化升级:集成 AI 质检系统,通过图像识别自动检测汽车装配质量,降低人工成本
  2. 物联网集成:为汽车添加 IoT 模块,实时采集生产过程中的设备数据,预测设备故障
  3. 供应链协同:对接零部件供应商系统,实现零部件库存自动预警和采购下单
  4. 客户定制化:支持客户在线定制汽车配置(如颜色、内饰、功能选装),系统自动生成生产订单
  5. 大数据分析:基于生产记录数据,分析各品牌 / 车型的生产效率、质检合格率,为生产优化提供数据支撑

8.4 关键经验总结

  1. 复杂系统设计的核心是 "解耦":通过分层架构、设计模式、微服务拆分等手段,降低模块间依赖
  2. 扩展能力是系统生命力的关键:在设计初期就要考虑未来可能的扩展场景,预留扩展接口
  3. 技术服务于业务:选择技术时,优先考虑是否贴合业务场景,而非追求 "最新最热"
  4. 重视基础能力建设:监控、日志、备份、故障处理等运维能力,是系统稳定运行的保障
  5. 代码规范不可忽视:统一的编码规范能提升代码可读性和可维护性,减少团队协作成本
相关推荐
王家羽翼-王羽3 小时前
nacos 3.1.0 运行主类报错 com.alibaba.cloud.nacos.logging.NacosLoggingAppRunListener
java
影子24014 小时前
oralce创建种子表,使用存储过程生成最大值sql,考虑并发,不考虑并发的脚本,plsql调试存储过程,java调用存储过程示例代码
java·数据库·sql
阿波罗尼亚4 小时前
设计原则(一)Head First设计模式
设计模式
武子康4 小时前
Java-172 Neo4j 访问方式实战:嵌入式 vs 服务器(含 Java 示例与踩坑)
java·服务器·数据库·sql·spring·nosql·neo4j
程序猿DD4 小时前
深入探索剖析 JVM 的启动过程
java
Arva .4 小时前
ConcurrentHashMap 的线程安全实现
java·开发语言
听风吟丶4 小时前
Java 9+ 模块化系统(Jigsaw)实战:从 Jar 地狱到模块解耦的架构升级
java·架构·jar
昂子的博客4 小时前
Redis缓存 更新策略 双写一致 缓存穿透 击穿 雪崩 解决方案... 一篇文章带你学透
java·数据库·redis·后端·spring·缓存