使用泛型时组合模式的可扩展性及类型安全API设计问询
泛型加持下组合模式的可扩展性
咱们先搭建一个实际场景:现有这么一套对象层级体系——Group、Person、Address,还有若干具体实现类:ImmutableGroup、PeopleyPerson、MonsterPerson、PostalAddress(提供getZip() :: String方法)、EmailAddress(提供getDomain() :: String方法)。咱们的核心目标是让API客户端能以类型安全的方式使用这些类型,比如客户端想写出group.personAt(0).getAddress().getDomain()这种流畅的链式调用,而通过把Group定义为Group<? extends PeopleyPerson<EmailAddress>> group就能完美实现,这到底意味着什么?
这个泛型定义的核心作用
- 首先,
Group<? extends PeopleyPerson<EmailAddress>>明确了:这个Group中的元素,至少是PeopleyPerson类型,或者它的子类(比如如果MonsterPerson继承了PeopleyPerson,那它也能被放进这个Group),而且这些Person关联的地址类型固定为EmailAddress。这样客户端调用personAt(0)拿到的是PeopleyPerson<EmailAddress>,接着调用getAddress()必然得到EmailAddress,自然能直接调用getDomain(),全程无需强制类型转换,完全由编译器保障类型安全。 - 如果客户端需要处理关联
PostalAddress的Person,只需要把Group的泛型调整为Group<? extends PeopleyPerson<PostalAddress>>,此时链式调用就可以顺畅地写成group.personAt(0).getAddress().getZip(),同样保持类型安全。 - 当后续需要新增
Person子类(比如RobotPerson)或者新的Address类型(比如PhoneAddress)时,只要让新的Person类继承PeopleyPerson,然后定义对应的Group<? extends PeopleyPerson<PhoneAddress>>,客户端就能直接基于新类型进行链式调用,完全不需要修改Group的核心代码——这就是泛型给组合模式带来的超强可扩展性:新增实现类不破坏原有结构,同时始终保持类型安全。
对比无泛型实现的优势
如果不用泛型,你可能需要编写大量重载方法,或者在代码中频繁进行强制类型转换,不仅代码冗余,还很容易出现ClassCastException这类运行时错误。而泛型的写法让编译器提前帮你做类型检查,把错误扼杀在编译阶段,同时代码也更简洁易读。
内容的提问来源于stack exchange,提问作者Dan Gravell
相关产品推荐
相关产品推荐

