深色模式
设计原则与常见模式
面向全栈岗位的语言无关基础。先口述定义与场景,再解释一致性、性能和故障边界;产品特有行为会明确标注。
1. 高内聚、低耦合如何落实?
展开答案与追问
参考答案: 把围绕同一业务能力变化的规则聚在一起,通过清晰契约与其他模块协作。避免跨层读取内部状态,控制依赖方向。衡量标准是改一个需求会波及哪些模块,而不是文件越多越解耦。
追问与易错点: 例如将定价规则与订单落库分离,但不为了分层制造只有转发作用的十层接口。
2. 单一职责是不是一个类只能有一个方法?
展开答案与追问
参考答案: 不是。单一职责关注变化原因与责任归属;多个方法可以共同实现一个内聚能力。职责划分要结合业务变化,过度拆分也会增加协作成本。
追问与易错点: 用“谁会要求它变化”判断,比按代码行数划分更有价值。
3. 开闭原则和策略模式如何结合?
展开答案与追问
参考答案: 稳定流程依赖策略契约,不同计价、校验或路由规则实现该契约,新增策略时尽量不修改核心流程。只有存在真实变化轴时才值得抽象。
追问与易错点: 不能承诺永远不修改旧代码;需求改变契约时仍需演进。
4. 依赖倒置和依赖注入是一回事吗?
展开答案与追问
参考答案: 依赖倒置是让高层业务依赖稳定抽象而非具体技术细节;依赖注入是从外部提供依赖的一种实现手段。可以通过函数参数、构造器或工厂实现,不必依赖某种框架。
追问与易错点: 例如订单服务接收支付网关契约,测试可替换为受控实现,而不是内部直接创建第三方客户端。
5. 接口隔离与最少知识原则如何理解?
展开答案与追问
参考答案: 调用者只依赖需要的能力,模块通过较小公共契约交流,减少对深层对象结构的了解。这样内部重构不必迫使所有消费者改动。
追问与易错点: 不要机械禁止链式调用;关键是是否泄露了不稳定的内部依赖关系。
6. 工厂、适配器和装饰器分别用于什么?
展开答案与追问
参考答案: 工厂集中创建与选择对象,适配器转换不兼容的契约,装饰器在保持契约的前提下附加行为。它们可组合使用,但应说明实际变化点和成本。
追问与易错点: 例:工厂选择存储实现,适配器统一供应商 SDK,装饰器增加指标与重试;重试前仍需核实幂等。
7. 观察者与发布订阅有什么区别?
展开答案与追问
参考答案: 观察者通常由被观察对象维护订阅并通知;发布订阅经中介或主题路由,使发布者不必直接知道订阅者。两者都需要处理退订、错误传播、顺序和生命周期。
追问与易错点: 进程内事件总线与持久消息系统的可靠性完全不同,不能混为一谈。
8. 状态机适合解决哪些业务问题?
展开答案与追问
参考答案: 将允许状态、事件、转移和约束显式化,适合订单、审批、上传或发布流程。用条件更新或事务保证转移原子性,记录审计事件,并处理重复或迟到的事件。
追问与易错点: 订单已取消后收到支付成功回调怎么办?需要补偿或退款规则,不能简单覆盖为已支付。
9. 组合优于继承应该如何理解?
展开答案与追问
参考答案: 通过组合小能力降低深继承带来的隐式依赖,便于替换与测试。继承仍适用于稳定的可替代关系;关键是子类型是否遵守父类型的行为契约,而不是一律禁止继承。
追问与易错点: 前端组件组合、后端策略对象和中间件都能体现组合思想。
10. DRY、KISS 与 YAGNI 冲突时怎么判断?
展开答案与追问
参考答案: 避免重复的业务知识,但不要仅因代码形似就过早合并;优先简单且可演进的实现,不提前为未经验证的需求堆叠扩展点。以变化频率、错误风险和维护成本作判断。
追问与易错点: 两个看似相同的表单可能属于不同业务规则,强行复用会形成大量条件参数。