如何将业务逻辑与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
相关产品推荐
相关产品推荐

