RPA工程化实践:三种核心设计模式让复杂流程优雅可控


一、为什么RPA需要设计模式?

在回答这个问题前,我们先看一个典型的复杂RPA场景:企业财务自动化需要从多个系统获取数据(ERP、CRM、银行),经过清洗、验证、转换,然后生成报表并上传至OA系统,期间涉及多次人工审批、异常处理、重试和日志记录。

如果采用传统脚本方式:

  • 所有逻辑堆砌在单个函数中,上千行代码难以阅读理解;
  • 增加一个新数据源,需要修改核心流程,极易引入bug;
  • 状态变更散落在各处,无法保证一致性;
  • 无法复用相同的数据处理逻辑。

而设计模式正是为了解决这类问题而生。它们将变化的部分封装,将稳定的部分抽象,让代码结构清晰,变更局部化。下面,我们将逐一深入三种模式。


二、流程控制模式:让流程灵活可控

2.1 模式定义

流程控制模式并不是单一的设计模式,而是一组用于组织业务流程执行逻辑的模式组合,常见的有:

  • 模板方法模式(Template Method):定义流程的骨架,将可变步骤延迟到子类实现。
  • 策略模式(Strategy):封装不同的业务规则,使它们可以互相替换。
  • 责任链模式(Chain of Responsibility):为请求创建处理链,每个处理者决定是否处理或传递给下一个。

在RPA中,一个完整业务流程往往由多个步骤组成,步骤可能因客户、环境、数据类型而异。流程控制模式可以帮助我们将步骤的"顺序结构"与"具体实现"分离。

2.2 模板方法模式实现流程骨架

假设我们有一个通用的数据导入流程:读取数据 → 清洗 → 验证 → 转换 → 写入目标系统。不同场景下,清洗、验证、转换的具体规则可能不同,但流程顺序固定。

python 复制代码
from abc import ABC, abstractmethod

class DataImportPipeline(ABC):
    """模板类:定义流程骨架"""
    
    def run(self, source):
        """模板方法,定义了算法骨架"""
        data = self.extract(source)
        cleaned = self.clean(data)
        validated = self.validate(cleaned)
        transformed = self.transform(validated)
        self.load(transformed)
    
    def extract(self, source):
        """默认实现,子类可覆盖"""
        print(f"从 {source} 提取原始数据")
        return {"raw": source}
    
    @abstractmethod
    def clean(self, data):
        """子类必须实现清洗逻辑"""
        pass
    
    @abstractmethod
    def validate(self, data):
        """子类必须实现验证逻辑"""
        pass
    
    @abstractmethod
    def transform(self, data):
        """子类必须实现转换逻辑"""
        pass
    
    def load(self, data):
        """默认实现,子类可覆盖"""
        print(f"加载数据到目标系统: {data}")

class ErpInvoicePipeline(DataImportPipeline):
    """ERP发票导入流程"""
    
    def clean(self, data):
        print("清洗ERP发票数据:去空格、格式统一")
        # 具体清洗代码
        return data
    
    def validate(self, data):
        print("验证发票必需字段")
        # 验证逻辑
        return data
    
    def transform(self, data):
        print("转换为财务系统格式")
        return {"finance": data}

优点

  • 流程结构稳定,复用性强;
  • 新增一种数据源只需实现新的子类,不影响已有流程;
  • 符合开闭原则。

2.3 策略模式实现可插拔的步骤

有时流程的某一步有多种算法可选(如不同的数据加密方式、不同的文件解析器),使用策略模式可以避免大量的if-else。

python 复制代码
from typing import Protocol

class ValidationStrategy(Protocol):
    def validate(self, data):
        ...

class StrictValidation:
    def validate(self, data):
        print("严格校验:所有字段必填")
        return all(data.values())

class LooseValidation:
    def validate(self, data):
        print("宽松校验:只检查关键字段")
        return data.get("id") is not None

class DataProcessor:
    def __init__(self, validation_strategy: ValidationStrategy):
        self._strategy = validation_strategy
    
    def process(self, data):
        if not self._strategy.validate(data):
            raise ValueError("数据校验失败")
        # 继续处理
        print("数据处理成功")

# 使用
processor = DataProcessor(StrictValidation())
processor.process({"id": 1, "name": "test"})  # 通过

2.4 责任链模式实现多级审批流

在RPA中常遇到需要多级审批的业务,如采购订单:部门主管 → 财务 → 总经理。责任链模式让每个审批者独立,易于添加或调整顺序。

python 复制代码
from abc import ABC, abstractmethod

class Approver(ABC):
    def __init__(self):
        self._next = None
    
    def set_next(self, approver):
        self._next = approver
        return approver
    
    @abstractmethod
    def process(self, request):
        pass

class ManagerApprover(Approver):
    def process(self, request):
        if request.amount <= 10000:
            print(f"部门经理审批通过:金额{request.amount}")
            return True
        elif self._next:
            return self._next.process(request)
        return False

class FinanceApprover(Approver):
    def process(self, request):
        if request.amount <= 50000:
            print(f"财务审批通过:金额{request.amount}")
            return True
        elif self._next:
            return self._next.process(request)
        return False

class CeoApprover(Approver):
    def process(self, request):
        print(f"CEO最终审批:金额{request.amount}")
        return True

# 构建责任链
manager = ManagerApprover()
finance = FinanceApprover()
ceo = CeoApprover()
manager.set_next(finance).set_next(ceo)

# 发起请求
class Request:
    def __init__(self, amount):
        self.amount = amount

manager.process(Request(8000))   # 经理审批
manager.process(Request(30000))  # 财务审批
manager.process(Request(80000))  # CEO审批

流程控制模式的RPA应用场景

  • 多系统数据同步流程(模板方法)
  • 根据不同客户配置不同的业务规则(策略)
  • 采购订单审批、工单流转(责任链)

三、数据管道模式:打造可复用的数据处理链

3.1 模式概述

数据管道模式(Pipeline Pattern)源自Unix管道哲学,它将数据处理过程分解为一系列独立的处理单元(过滤器),每个单元接收输入、处理后输出,并传递给下一个单元。这种模式非常适合RPA中常见的数据抽取-转换-加载(ETL)场景。

3.2 核心要素

  • 数据源:提供原始数据(文件、数据库、API)
  • 过滤器:对数据进行操作(清洗、转换、验证、增强)
  • 管道:连接过滤器的通道,控制数据流动
  • 数据汇:最终存储或输出

3.3 Python实现一个轻量级管道

我们可以用装饰器或链式调用来实现管道。

python 复制代码
from typing import Callable, Any

class Pipeline:
    """通用管道类,支持多个处理器"""
    def __init__(self):
        self._handlers = []
    
    def add(self, handler: Callable[[Any], Any]):
        self._handlers.append(handler)
        return self  # 支持链式调用
    
    def execute(self, initial_data):
        data = initial_data
        for handler in self._handlers:
            data = handler(data)
        return data

# 定义各个处理函数
def extract_from_csv(file_path):
    print(f"从{file_path}读取CSV")
    return [{"id": 1, "name": "A"}, {"id": 2, "name": "B"}]

def clean_data(records):
    print("清洗数据:去除空格")
    for r in records:
        r["name"] = r["name"].strip()
    return records

def enrich_with_timestamp(records):
    print("添加时间戳")
    from datetime import datetime
    ts = datetime.now().isoformat()
    for r in records:
        r["processed_at"] = ts
    return records

def load_to_db(records):
    print(f"加载{len(records)}条记录到数据库")
    return True

# 构建管道
pipeline = Pipeline()
pipeline.add(extract_from_csv).add(clean_data).add(enrich_with_timestamp).add(load_to_db)

# 执行
pipeline.execute("data.csv")

输出

复制代码
从data.csv读取CSV
清洗数据:去除空格
添加时间戳
加载2条记录到数据库

3.4 管道模式的进阶:支持异步、条件分支

复杂场景下,可能需要根据数据内容走不同分支,或并行处理。我们可以对管道进行扩展,引入条件过滤、异常处理等。

python 复制代码
class ConditionalHandler:
    def __init__(self, condition, true_handler, false_handler=None):
        self.condition = condition
        self.true_handler = true_handler
        self.false_handler = false_handler
    
    def __call__(self, data):
        if self.condition(data):
            return self.true_handler(data)
        elif self.false_handler:
            return self.false_handler(data)
        return data

应用场景

  • 从多个数据源抽取并统一格式
  • 数据质量校验与修复
  • 实时数据流处理(如监控日志并触发RPA动作)

3.5 数据管道模式的优势

  • 解耦:每个处理器独立开发、测试、维护
  • 复用:相同处理器可在不同管道中使用
  • 可测性:每个单元可单独测试
  • 可观测性:可在管道中插入日志、监控节点

四、状态机模式:让业务流程状态清晰可控

4.1 为什么需要状态机?

在RPA中,很多业务流程具有明确的状态,例如:

  • 订单处理:待支付 → 已支付 → 已发货 → 已完成
  • 工单审批:待提交 → 主管审批 → 经理审批 → 归档
  • 数据同步:待同步 → 同步中 → 同步成功 / 同步失败 → 重试

如果使用简单的变量和if-else管理状态,当状态增多、转换条件复杂时,代码极易出错。有限状态机(FSM) 将状态、事件、转换规则显式定义,确保系统始终处于合法状态。

4.2 状态机的核心元素

  • 状态(State):系统可能处于的稳定阶段
  • 事件(Event):触发状态转换的输入
  • 转换(Transition):定义在某个状态下发生某个事件后,转移到哪个新状态,并执行相应动作
  • 动作(Action):状态转换时执行的业务逻辑

4.3 使用Python实现状态机

我们可以使用transitions库快速构建,也可以手动实现轻量级版本。

示例:使用transitions库(推荐)
python 复制代码
pip install transitions
python 复制代码
from transitions import Machine

class InvoiceOrder:
    states = ['pending', 'paid', 'shipped', 'completed', 'cancelled']
    
    def __init__(self, name):
        self.name = name
        self.machine = Machine(model=self, states=InvoiceOrder.states, initial='pending')
        
        # 定义转换
        self.machine.add_transition('pay', 'pending', 'paid', after='after_pay')
        self.machine.add_transition('ship', 'paid', 'shipped', after='after_ship')
        self.machine.add_transition('complete', 'shipped', 'completed', after='after_complete')
        self.machine.add_transition('cancel', ['pending', 'paid'], 'cancelled', after='after_cancel')
    
    def after_pay(self):
        print(f"订单{self.name}已支付,记录财务信息")
    
    def after_ship(self):
        print(f"订单{self.name}已发货,更新物流")
    
    def after_complete(self):
        print(f"订单{self.name}已完成")
    
    def after_cancel(self):
        print(f"订单{self.name}已取消,释放库存")

# 使用
order = InvoiceOrder("ORD001")
order.pay()      # 支付
order.ship()     # 发货
order.complete() # 完成
order.cancel()   # 此时状态已是completed,不允许取消,会触发异常
手动实现轻量级状态机(用于理解原理)
python 复制代码
class StateMachine:
    def __init__(self):
        self.state = 'initial'
        self.transitions = {
            ('initial', 'start'): 'processing',
            ('processing', 'success'): 'completed',
            ('processing', 'fail'): 'error',
            ('error', 'retry'): 'processing',
        }
    
    def trigger(self, event):
        key = (self.state, event)
        if key in self.transitions:
            old_state = self.state
            self.state = self.transitions[key]
            self.on_transition(old_state, event)
        else:
            raise Exception(f"非法转换:{self.state} -> {event}")
    
    def on_transition(self, old, event):
        print(f"{old} 通过 {event} 转为 {self.state}")

4.4 状态机在RPA中的高级应用

场景:一个需要与用户交互的RPA任务,例如自动填报系统,可能被用户暂停、恢复、手动干预。状态机可以清晰定义这些交互状态。

python 复制代码
class RpaTask:
    states = ['idle', 'running', 'paused', 'error', 'completed']
    
    def __init__(self, task_id):
        self.task_id = task_id
        self.machine = Machine(model=self, states=RpaTask.states, initial='idle')
        self.machine.add_transition('start', 'idle', 'running')
        self.machine.add_transition('pause', 'running', 'paused')
        self.machine.add_transition('resume', 'paused', 'running')
        self.machine.add_transition('fail', 'running', 'error')
        self.machine.add_transition('retry', 'error', 'running')
        self.machine.add_transition('complete', 'running', 'completed')
    
    def on_enter_running(self):
        # 启动实际业务流程
        pass

优点

  • 状态流转显式化,易于理解和测试
  • 避免非法状态转换
  • 可以轻松添加持久化(将状态保存到数据库),实现断点续传

五、三种模式的协同应用

在实际RPA项目中,这三种模式往往同时使用,互相配合。下面通过一个综合案例展示它们的协同:

场景:一个企业RPA需要定期从多个ERP系统抽取销售数据,经过清洗、验证、转换,然后通过审批流程,最后同步到数据仓库。同时,整个过程需要记录状态,支持断点续传和重试。

  1. 流程控制模式:使用模板方法定义整体流程骨架(抽取→清洗→转换→审批→加载)。其中审批环节使用责任链模式实现多级审批。
  2. 数据管道模式:在数据处理阶段,构建数据管道,将清洗、验证、转换作为独立的过滤器,方便复用和测试。
  3. 状态机模式:为每个批次任务维护状态(待抽取、抽取中、清洗中、审批中、同步中、完成、失败),使用状态机管理,确保任务状态转换正确,并支持重试。

通过这种组合,代码结构清晰,每个模块职责单一,系统整体健壮性大幅提升。


相关推荐
就是个名称2 小时前
echart绘制天顶图
linux·前端·javascript
AI大法师2 小时前
字标Logo设计指南:中文品牌如何用字体做出高级感与辨识度
人工智能·设计模式
x-cmd2 小时前
[260326] x-cmd v0.8.10:跨 Shell 统一配置命令短名;自动装好依赖运行 WhisperLiveKit 实时语音转写
linux·人工智能·ai·whisper·shortcut·x-cmd
zhuyan1083 小时前
【AI编程】aider安装记录
linux·运维·ai编程
书山有鹿3 小时前
MaxKB v2.7.0 Rocky Linux 9 部署手册
linux·运维·maxkb·rockylinux 9
Mapleay3 小时前
ALSA PCM 数据搬运模式
linux
Yu_Lijing3 小时前
基于C++的《Head First设计模式》笔记——中介者模式
笔记·设计模式·中介者模式
feng68_3 小时前
Ansible还原数据库节点
linux·运维·数据库·ansible
来鸟 鸣间3 小时前
oops问题定位记录
linux·c语言