返利软件架构设计:多平台适配的抽象工厂模式实践

返利软件架构设计:多平台适配的抽象工厂模式实践

大家好,我是省赚客APP研发者阿可!省赚客APP(juwatech.cn)需同时对接淘宝联盟、京东联盟、拼多多开放平台等多个电商返利渠道。各平台在商品解析、佣金查询、订单回调等接口上存在显著差异,若采用硬编码分支判断,将导致代码高度耦合、难以维护。为此,我们基于抽象工厂模式设计了一套统一的多平台适配架构,实现"一次调用,多端兼容"。本文将结合核心接口定义与具体实现,详解该模式在返利系统中的落地。

抽象产品接口定义

首先定义各平台共有的能力契约:

java 复制代码
package juwatech.cn.platform;

public interface ProductParser {
    ParsedProduct parse(String input);
}

public interface CommissionCalculator {
    BigDecimal calculateCommission(String itemId, Long userId);
}

public interface CallbackVerifier {
    boolean verify(Map<String, String> params, String signature);
}

public interface PlatformClient {
    String getPlatformCode();
    ProductParser getProductParser();
    CommissionCalculator getCommissionCalculator();
    CallbackVerifier getCallbackVerifier();
}

其中 ParsedProduct 为标准化商品模型:

java 复制代码
public class ParsedProduct {
    private String platform;
    private String itemId;
    private String title;
    private BigDecimal price;
    private String shopName;
    // getters/setters
}

抽象工厂基类与注册机制

定义抽象工厂基类,并通过 Spring 自动注册所有实现:

java 复制代码
package juwatech.cn.platform.factory;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

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

@Component
public abstract class AbstractPlatformFactory implements InitializingBean {

    private static final Map<String, PlatformClient> CLIENT_REGISTRY = new ConcurrentHashMap<>();

    public static PlatformClient getClient(String platformCode) {
        PlatformClient client = CLIENT_REGISTRY.get(platformCode);
        if (client == null) {
            throw new IllegalArgumentException("Unsupported platform: " + platformCode);
        }
        return client;
    }

    @Override
    public void afterPropertiesSet() {
        PlatformClient client = createClient();
        CLIENT_REGISTRY.put(client.getPlatformCode(), client);
    }

    protected abstract PlatformClient createClient();
}

淘宝联盟具体工厂实现

以淘宝为例,实现其专属工厂:

java 复制代码
package juwatech.cn.platform.taobao;

@Component
public class TaobaoPlatformFactory extends AbstractPlatformFactory {

    @Autowired
    private TaobaoApiClient taobaoApiClient;

    @Override
    protected PlatformClient createClient() {
        return new TaobaoPlatformClient(taobaoApiClient);
    }
}

class TaobaoPlatformClient implements PlatformClient {
    private final TaobaoApiClient apiClient;

    public TaobaoPlatformClient(TaobaoApiClient apiClient) {
        this.apiClient = apiClient;
    }

    @Override
    public String getPlatformCode() {
        return "TAOBAO";
    }

    @Override
    public ProductParser getProductParser() {
        return new TaobaoProductParser(apiClient);
    }

    @Override
    public CommissionCalculator getCommissionCalculator() {
        return new TaobaoCommissionCalculator(apiClient);
    }

    @Override
    public CallbackVerifier getCallbackVerifier() {
        return new TaobaoCallbackVerifier();
    }
}

具体解析器实现:

java 复制代码
class TaobaoProductParser implements ProductParser {
    private final TaobaoApiClient client;

    public TaobaoProductParser(TaobaoApiClient client) {
        this.client = client;
    }

    @Override
    public ParsedProduct parse(String input) {
        String itemId = TaobaoUrlUtils.extractItemId(input);
        TaobaoItem item = client.getItemInfo(itemId);
        return new ParsedProduct()
            .setPlatform("TAOBAO")
            .setItemId(item.getNumIid())
            .setTitle(item.getTitle())
            .setPrice(new BigDecimal(item.getZkFinalPrice()))
            .setShopName(item.getNick());
    }
}

拼多多工厂实现(对比展示差异)

java 复制代码
@Component
public class PddPlatformFactory extends AbstractPlatformFactory {
    @Override
    protected PlatformClient createClient() {
        return new PddPlatformClient(new PddOpenApiClient());
    }
}

class PddPlatformClient implements PlatformClient {
    private final PddOpenApiClient client;

    public PddPlatformClient(PddOpenApiClient client) {
        this.client = client;
    }

    @Override
    public String getPlatformCode() { return "PDD"; }

    @Override
    public ProductParser getProductParser() {
        return input -> {
            String goodsId = PddUrlUtils.extractGoodsId(input);
            PddGoods goods = client.getGoodsDetail(goodsId);
            return new ParsedProduct()
                .setPlatform("PDD")
                .setItemId(goods.getGoodsId())
                .setTitle(goods.getGoodsName())
                .setPrice(goods.getMinGroupPrice().divide(BigDecimal.valueOf(100)))
                .setShopName(goods.getMallName());
        };
    }

    @Override
    public CommissionCalculator getCommissionCalculator() {
        return (itemId, userId) -> {
            // 拼多多佣金需根据用户身份和活动动态计算
            return client.queryCommissionRate(itemId, userId);
        };
    }

    @Override
    public CallbackVerifier getCallbackVerifier() {
        return (params, sign) -> PddSignUtil.verify(params, appSecret, sign);
    }
}

统一服务入口调用

业务层无需感知平台细节,仅需传入平台标识:

java 复制代码
@Service
public class UnifiedCommissionService {

    public void processCallback(String platform, Map<String, String> params, String sign) {
        PlatformClient client = AbstractPlatformFactory.getClient(platform);
        
        if (!client.getCallbackVerifier().verify(params, sign)) {
            throw new SecurityException("Invalid signature for platform: " + platform);
        }

        String tradeId = params.get("trade_id");
        String itemId = params.get("item_id");
        Long userId = Long.valueOf(params.get("user_id"));

        BigDecimal commission = client.getCommissionCalculator().calculateCommission(itemId, userId);
        accountService.credit(userId, commission, "返利入账");

        commissionRecordMapper.insert(tradeId, itemId, userId, commission, platform);
    }

    public ParsedProduct parseProduct(String platform, String input) {
        PlatformClient client = AbstractPlatformFactory.getClient(platform);
        return client.getProductParser().parse(input);
    }
}

扩展性与测试优势

新增平台(如京东)只需:

  1. 实现 JdPlatformFactory
  2. 注入所需 API 客户端;
  3. 无需修改任何现有业务逻辑。

单元测试可轻松 Mock 特定平台 Client:

java 复制代码
@Test
void testTaobaoParse() {
    PlatformClient mockClient = mock(PlatformClient.class);
    when(mockClient.getProductParser()).thenReturn(input -> new ParsedProduct().setTitle("测试商品"));
    
    // 替换注册表(测试专用)
    AbstractPlatformFactory.CLIENT_REGISTRY.put("TAOBAO", mockClient);
    
    ParsedProduct result = service.parseProduct("TAOBAO", "https://...");
    assertEquals("测试商品", result.getTitle());
}

本文著作权归聚娃科技省赚客app开发者团队,转载请注明出处!

相关推荐
写代码的【黑咖啡】2 小时前
深入理解 Python 中的函数
开发语言·python
ZePingPingZe2 小时前
秒杀-库存超卖&流量削峰
java·分布式
horizon72742 小时前
【Redis】Redis 分片集群搭建与故障转移实战指南
java·redis
想学后端的前端工程师2 小时前
【Java设计模式实战应用指南:23种设计模式详解】
java·开发语言·设计模式
小白勇闯网安圈2 小时前
Java的集合
java·开发语言
大学生资源网2 小时前
基于springboot的乡村信息化管理系统的研究与实现(源码+文档)
java·spring boot·后端
鹿角片ljp2 小时前
力扣 83: 删除排序链表中的重复元素(Java实现)
java·leetcode·链表
渣渣盟2 小时前
网络命令大全:轻松解决网络故障
开发语言·php