具体实现类属性存在差异场景下builder模式使用咨询:预订系统设计
当前实现的核心问题
你目前的通用ReservationBuilder设计本质是把两类不同预订的构建逻辑耦合在一起,违反单一职责原则,同时缺乏编译期的类型安全校验:调用方无法在编码阶段感知哪些属性设置方法对当前预订类型是无效的,只能依赖运行时的静默忽略或者报错,很容易埋下线上隐患。
两种方案的适配场景
1. 抽象Builder + 具体Builder实现
如果你的预订实例有大量可选属性,创建时需要灵活组合不同参数,优先选择该方案:
- 定义抽象
ReservationBuilder基类,将日期、位置等公共属性的设置方法收敛到基类中,通过泛型支持链式调用 - 为每类预订实现独立的具体Builder:仅在对应类型的Builder中暴露该类型支持的独有属性设置方法,比如支持携带随行客人的预订Builder才提供
addGuests()方法,支持午餐服务的预订Builder才提供applyLunchService()方法 - 各具体Builder的
build()方法仅负责生成对应类型的预订实例
示例代码片段(Java为例):
// 抽象Builder基类 public abstract class ReservationBuilder<T extends Reservation, B extends ReservationBuilder<T, B>> { protected LocalDate date; protected String location; public B date(LocalDate date) { this.date = date; return self(); } public B location(String location) { this.location = location; return self(); } protected abstract B self(); public abstract T build(); } // 支持携带客人的预订具体Builder public class GuestAllowedReservationBuilder extends ReservationBuilder<GuestAllowedReservation, GuestAllowedReservationBuilder> { private List<Guest> guestList = new ArrayList<>(); public GuestAllowedReservationBuilder addGuest(Guest guest) { guestList.add(guest); return this; } @Override protected GuestAllowedReservationBuilder self() { return this; } @Override public GuestAllowedReservation build() { return new GuestAllowedReservation(date, location, guestList); } }
该方案的优势是编译期即可阻止调用方使用无效的属性设置方法,类型安全性高,后续新增预订类型时仅需新增对应的Builder即可,符合开闭原则。
2. 工厂模式
如果你的两类预订的必填/可选属性都非常固定,创建逻辑简单,没有太多参数组合需求,直接选择工厂模式即可,无需引入Builder的额外复杂度:
- 可以实现
ReservationFactory类,通过不同的静态工厂方法生成不同类型的预订实例 - 不同类型的预订所需的独有参数直接作为对应工厂方法的入参,比如
createGuestAllowedReservation()方法接收客人列表参数,createLunchAllowedReservation()方法接收午餐申请参数
该方案的优势是实现轻量化,没有多余的抽象层级,适合业务逻辑稳定、预订类型不会频繁扩展的场景。
选型建议
如果未来可能扩展更多预订类型,或者单类预订的可选参数超过3个,优先选择抽象Builder方案。如果当前仅有固定两类预订、参数配置逻辑简单,直接使用工厂模式即可。
内容的提问来源于stack exchange,提问作者Nicolas Van Damme
相关产品推荐
相关产品推荐

