# 常见设计模式及使用 本篇只写这套脚手架里会碰到的三种写法。名称用来对照代码,不展开其他模式。 ## 目录 - [依赖注入](#依赖注入) - [仓储](#仓储) - [观察者](#观察者) ## 依赖注入 调用方不创建依赖,容器按构造函数传入。`SecurityApplication` 需要仓储和 `TokenStore` 时,只声明参数类型,不写 `new SecurityRepository()`。 依赖倒置、注入方式和 `Singleton`、`Transient`、`@bindAs` 的用法见 [DI是什么](./DI是什么.md)。 ## 仓储 仓储把「业务要的数据」和「数据放在哪」分开。 `ISecurityRepository` 声明 `login`,返回 `LoginResult`。用例只调用这个方法,再把 `accessToken` 写入 `TokenStore`。`SecurityRepository` 才知道要访问 `/auth/login`,并把响应收成 `User`。 项目模块只有一个端口 `IProjectRepository`,声明 `list`、`get`、`save`。本地实现走 IndexedDB,远程实现走 `Http`,都实现这个端口。`ProjectApplication` 按 `store` 选择其中一个。 因此 `domain` 不出现 axios 和 IndexedDB,`infra` 不决定登录成功后要做什么。 ## 观察者 状态变化后,订阅者自己更新。本仓库有两处。 MobX 的 `observable` 字段变化时,包了 `observer` 的组件重绘。这是页面状态到界面的观察者。 `TokenStore.save` 和 `TokenStore.remove` 调用 `notifyAuthChanged`。`useAuthenticated` 通过 `subscribeAuth` 收到 `AUTH_CHANGED` 后再读一次 `hasSession`。登录态变化时,首页不必自己轮询。