我已将真实代码简化为说明这一点的最小示例。请原谅缺少 setter/getter 等。
想象一下,我们有几个客户按顺序浏览的网页。这里的用例是:-
- 用户选择他们想要的书
- 用户选择是否希望通过邮寄或电子邮件发送它以及相关的详细信息
- 系统完成订单
这个问题集中在两种交付方式上。这被建模如下:
interface DeliveryDetails
{
// Implementations of this have nothing in common other than that they
// fulfil the same logical role.
}
class EmailDeliveryDetails implements DeliveryDetails
{
String emailAddress; // It really has a constructor and getter, I promise.
}
class PostalDeliveryDetails implements DeliveryDetails
{
String streetAddress;
String Country;
}
现在,为了表示用户在浏览页面时输入的信息,我们有这个类:
class PurchaseData
{
String title;
DeliveryDetails deliveryDetails;
}
当用户浏览网页时,信息存储在PurchaseData
. 如果用户返回一个页面,我们可以向他们展示他们之前输入的内容。在用户确认并交付图书后,引用ordeliveryDetails
的一个实例。PostalDeliveryDetails
EmailDeliveryDetails
总之,当用户确认他们的信息时:
// Some code in a factory
if ( purchaseData.deliveryDetails instanceof EmailDelivery )
{
// construct a EmailDeliveryService( purchaseData, SMTP details, etc ... )
}
if ( purchaseData.deliveryDetails instanceof PostalDelivery )
{
// construct a PostalDeliveryService( purchaseData, etc ... )
}
}
Delivery
接口没有方法让我很困扰。
这是由于电子邮件和邮政投递之间的差异造成的。
我认为这DeliveryDetails.deliver()
不是一个好方法,因为这会强制实现静态获取诸如 SMTP 服务器地址之类的东西。这会混淆关注点(管道与用户输入的信息)。
如果您必须存储任意类型的东西,泛型可能很有用。无法使用泛型 ( PurchaseData<T extends Delivery>
),因为在创建 PurchaseData 实例时不知道交付类型。无论如何,这对工厂没有帮助。
这个空界面可以吗?有没有更好的方法来设计这段代码?