面试题答案
一键面试设计抽象类考虑方面
- 与其他模块耦合度
- 接口隔离:抽象类应通过定义清晰、狭窄的接口与其他模块交互。比如在电商系统中,订单处理抽象类只暴露与订单处理直接相关的方法,如
processOrder(Order order)
,避免暴露过多内部实现细节给其他模块,降低耦合。 - 依赖倒置:让其他模块依赖抽象类而非具体实现类。例如在支付模块,依赖支付抽象类
Payment
,而不是具体的微信支付、支付宝支付实现类,使得支付方式变更时,其他模块无需大量修改。
- 接口隔离:抽象类应通过定义清晰、狭窄的接口与其他模块交互。比如在电商系统中,订单处理抽象类只暴露与订单处理直接相关的方法,如
- 对不同业务场景的适配性
- 抽象方法与具体方法结合:在抽象类中定义抽象方法,让子类根据不同业务场景实现。如在报表生成抽象类中,定义
generateReport()
抽象方法,销售报表子类和财务报表子类实现不同的生成逻辑。同时,抽象类可包含一些通用的具体方法,如报表数据的基本校验方法。 - 参数化配置:通过参数化方式使抽象类适配不同业务场景。例如在数据处理抽象类中,通过构造函数传入数据处理规则的配置参数,不同子类根据配置执行不同处理逻辑。
- 抽象方法与具体方法结合:在抽象类中定义抽象方法,让子类根据不同业务场景实现。如在报表生成抽象类中,定义
- 提升系统可测试性
- Mock 友好:抽象类应便于创建 Mock 对象进行单元测试。比如在外部服务调用抽象类中,可通过抽象方法定义服务调用逻辑,在测试时创建 Mock 子类,模拟服务返回结果,对依赖该抽象类的模块进行独立测试。
- 依赖注入:利用依赖注入将抽象类的依赖注入到使用它的类中,便于在测试时替换为 Mock 对象。例如在用户认证模块中,将认证抽象类通过构造函数注入到业务逻辑类中,测试时可注入 Mock 的认证实现,测试业务逻辑对认证结果的处理。
避免过度抽象或抽象不足问题
- 避免过度抽象
- 基于实际需求:以实际业务场景为导向进行抽象,避免为了抽象而抽象。例如在一个简单的博客系统中,文章管理模块如果过度抽象,将文章的发布、编辑、删除等操作抽象到多层抽象类中,而实际业务并没有那么复杂的变化需求,就会增加系统复杂性。应根据实际文章管理需求,合理抽象出必要的操作方法在抽象类中。
- 验证抽象必要性:每一个抽象类和抽象方法都要经过验证,看是否真的有不同的实现需求。如果某个抽象方法只有一个子类实现方式且未来不太可能有变化,那么这个抽象可能是过度的,可以将其合并到抽象类的具体方法中。
- 避免抽象不足
- 挖掘共性:仔细分析业务场景,找出不同实现之间的共性部分进行抽象。例如在一个多渠道消息推送系统中,短信推送、邮件推送、APP 推送虽然实现方式不同,但都有发送消息的基本流程,如构建消息内容、连接推送服务等,应将这些共性抽象到消息推送抽象类中。
- 预留扩展点:在设计抽象类时,考虑未来业务的扩展性,预留一些抽象方法或钩子方法。比如在电商促销活动抽象类中,预留
customizePromotion()
抽象方法,以便未来有新的促销活动类型时,子类可以实现该方法进行扩展,避免因为抽象不足导致系统难以扩展新业务。