You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将业务逻辑与Rx分离并应用Uncle Bob整洁架构?

当然可以把Rx从整洁架构的核心层完全分离出来——这正是整洁架构「依赖向内」原则的典型应用场景,我来给你拆解具体怎么做:

核心思路:用抽象端口隔离Rx依赖

整洁架构的核心要求是实体和业务逻辑(用例)不依赖任何外部工具或框架,包括Rx。所以我们需要把Rx的异步逻辑完全封装在适配器层,核心层只定义抽象的「异步契约」(也就是整洁架构里的「端口」)。

第一步:核心层定义抽象的认证缓存接口

核心层只关心「需要做什么」,不关心「怎么异步实现」。比如我们定义一个AuthCachePort接口,以及配套的异步结果处理方式,完全不涉及Rx:

// 核心层 - 无任何外部依赖
public interface AuthCachePort {
    AsyncSubscribable<Credentials> getStoredCredentials();
    AsyncSubscribable<Void> storeCredentials(Credentials credentials);
    AsyncSubscribable<Void> clearCredentials();
}

// 核心层自定义的异步订阅契约
public interface AsyncSubscribable<T> {
    Subscription subscribe(ResultHandler<T> handler);
}

// 结果处理器接口,统一处理成功/失败场景
public interface ResultHandler<T> {
    void onSuccess(T value);
    void onFailure(Throwable error);
}

// 取消订阅的标准接口
public interface Subscription {
    void cancel();
}

// 用例类:只依赖抽象端口,业务逻辑完全独立
public class AuthUseCase {
    private final AuthCachePort authCache;

    public AuthUseCase(AuthCachePort authCache) {
        this.authCache = authCache;
    }

    public AsyncSubscribable<Credentials> getCachedCredentials() {
        // 这里只处理业务逻辑:比如校验凭证是否过期
        return authCache.getStoredCredentials()
                .map(this::validateCredentials);
    }

    private Credentials validateCredentials(Credentials credentials) {
        if (credentials == null || credentials.isExpired()) {
            throw new InvalidCredentialsException("凭证无效或已过期");
        }
        return credentials;
    }
}

第二步:适配器层用Rx实现抽象端口

这一层是唯一依赖Rx的地方,负责把Rx的异步逻辑适配到核心层的抽象接口上。比如我们用RxSharedPreferences做本地存储,实现AuthCachePort:

// 适配器层 - 仅依赖Rx和具体存储实现
public class RxAuthCacheAdapter implements AuthCachePort {
    private final RxSharedPreferences rxSharedPreferences;
    private final Gson gson;

    public RxAuthCacheAdapter(RxSharedPreferences rxSharedPreferences, Gson gson) {
        this.rxSharedPreferences = rxSharedPreferences;
        this.gson = gson;
    }

    @Override
    public AsyncSubscribable<Credentials> getStoredCredentials() {
        // 用Rx处理异步读取逻辑
        Observable<Credentials> credentialsObservable = rxSharedPreferences
                .getString("cached_credentials")
                .map(json -> gson.fromJson(json, Credentials.class))
                .onErrorResumeNext(Observable.empty());

        // 适配到核心层的AsyncSubscribable接口
        return handler -> {
            Disposable disposable = credentialsObservable.subscribe(
                    credentials -> handler.onSuccess(credentials),
                    error -> handler.onFailure(error)
            );
            return disposable::dispose;
        };
    }

    @Override
    public AsyncSubscribable<Void> storeCredentials(Credentials credentials) {
        String json = gson.toJson(credentials);
        Observable<Void> storeObservable = rxSharedPreferences
                .getString("cached_credentials")
                .put(json)
                .toObservable()
                .map(ignored -> null);

        return handler -> {
            Disposable disposable = storeObservable.subscribe(
                    unused -> handler.onSuccess(null),
                    error -> handler.onFailure(error)
            );
            return disposable::dispose;
        };
    }

    // clearCredentials方法可参照上述逻辑实现
}

第三步:UI层按需适配(可选)

如果你的UI层已经在用Rx,可以再加一个轻量适配器,把核心层的AsyncSubscribable转换成Rx的Observable,让UI层可以直接用Rx的操作符:

// UI层适配器 - 仅用于适配核心层异步契约到Rx
public class RxAuthUseCaseWrapper {
    private final AuthUseCase authUseCase;

    public RxAuthUseCaseWrapper(AuthUseCase authUseCase) {
        this.authUseCase = authUseCase;
    }

    public Observable<Credentials> getCachedCredentials() {
        return Observable.create(emitter -> {
            Subscription subscription = authUseCase.getCachedCredentials().subscribe(new ResultHandler<>() {
                @Override
                public void onSuccess(Credentials credentials) {
                    emitter.onNext(credentials);
                    emitter.onComplete();
                }

                @Override
                public void onFailure(Throwable error) {
                    emitter.onError(error);
                }
            });
            emitter.setDisposable(subscription::cancel);
        });
    }
}

为什么这符合整洁架构?

  • 核心层完全独立:实体和用例不依赖Rx,甚至不依赖任何异步框架——如果以后想换成Kotlin协程、Java CompletableFuture,只需要替换适配器层,核心代码一行不用改。
  • 依赖方向正确:外层(适配器、UI)依赖核心层的抽象,核心层不依赖任何外层的具体实现,完全符合整洁架构的「依赖规则」。
  • 业务逻辑纯粹:用例里只处理认证相关的业务规则(比如凭证有效性校验),不用关心异步细节、存储细节,代码更简洁易维护。

内容的提问来源于stack exchange,提问作者Nandin Borjigin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:21:32