2012-10-22 101 views
0

我正在研究一个项目,我正在试图从一个持久模式转移到另一个模式。持久性设计模式

我看着在模式企业应用架构的,设计模式,并在这里this MSDN文章寻求帮助。我们目前的模式是MSDN文章中描述的活动记录模式。作为迈向更多模块化代码库的第一步,我们试图将我们的一些业务对象(又名表)分解为多个接口。

因此,举例来说,假设我有一个商店应用程序是这样的:

public interface IContactInfo 
{ 
    ... 
} 

public interface IBillingContactInfo: IContactInfo 
{ 
    ... 
} 

public interface IShippingContactInfo: IContactInfo 
{ 
    ... 

} 

public class Customer: IBillingContactInfo, IShippingContactInfo 
{ 
    #region IBillingContactInfo Implementation 
    ... 
    #endregion 

    #region IShippingContactInfo Implementation 
    ... 
    #endregion 

    public void Load(int customerID); 
    public void Save(); 
} 

Customer类代表了我们的客户表中的一行。即使Customer类是一行,它实际上也实现了两个不同的接口:IBillingContactInfo,IShippingContactInfo。

从历史上看,我们没有那两个接口,我们只是在整个Customer对象周围传递这些接口,然后做出我们想要的任何更改并将其保存。

这里是问题出现的地方。现在我们有了这两个接口,我们可能有一个控件需要一个IContactInfo,将其显示给用户,并允许用户在错误的情况下进行纠正。目前我们的IContactInfo接口没有实现任何Save()以允许对其进行修改。

有关良好设计模式的任何建议,以避免此限制而无需完全切换到其他众所周知的解决方案?我真的不想通过并为我的所有接口添加Save()方法,但它可能是我最终需要做的。

+0

也许我错过了这个观点..但是你不能只在'IContactInfo'接口中包含'Load'和'Save'方法吗? –

+0

如果控件需要Save()的能力,为什么要采用IContactInfo?如果可能创建一个实现IContactInfo的SavableContactInfo类型,然后让该控件获取一个SavableContactInfo对象? – itsme86

+0

@SimonWhitehead我可以包含一个Load和Save,但有近100个表格,我们可能会将这些表格分解到接口中,以便确保在开始沿着这条路线前,我不会错过更明显和更好的战斗测试。 –

回答

0

通过简单地使IContactInfo实现IPersistable接口,您可以轻松地将Save()方法约束添加到继承的接口,该接口要求使用Save()方法。那么,所有具有IContactInfo的东西也有IPersistable,因此必须有Save()。您也可以使用ILoadableLoad(int ID) - 或者更多的语义正确性IRetrievableRetrieve(int ID)来做到这一点。

尽管这完全取决于您如何使用ContactInfo对象。如果这与您的使用情况无关,请留下评论/更新您的问题,我会重新回答我的答案。

+0

我同意我们可以有'IPersistable',但我们必须将其添加到每个接口。在我的示例中,如何解决使用Save()? IBillContactInfo.Save()或IShippingContactInfo.Save()?我想我必须回到显式的接口实现上来,我担心这会是一个真正的痛苦,尽管我认为我必须用两个接口来做这件事,所以这可能是我最好的选择。我希望有一个我没有看到的神奇的子弹:)这也只是一个例子,所以不要太在意它。重要的问题是接口继承命名冲突。 –

+0

我的建议是将其添加到基础'IContactInfo'接口,然后由它下面的所有接口继承。至于“它的哪个版本”无关紧要,你只是简单地履行由“IPersistable”或其他方式所规定的合同。没有任何可以调用的“版本”。您可能会对类继承和重写产生困惑,它有自己的语义。 – tmesser

1

您计划拥有多少种IContactInfo的衍生产品?

也许我错过了点,但我认为你会做一个叫做ContactInfoBillTo类,并在每一个Customer实例ShipTo更好。由于您的IShippingContactInfoIBillingContactInfo接口继承自相同的IContactInfo接口,因此您的类将使用一组字段满足IContactInfo基本接口。这将是一个问题。

最好让这些独立的实例。然后,保存你的Customer更直截了当。

你打算进行持久化或保存到数据库或其他东西的序列化?

使用Customer和ContactInfo的具体类型肯定会覆盖前两个。

(平面文件将努力为您的原始设置,但我希望你是不是对规划。)

我认为这一切都归结到你期望多少IContactInfo的衍生物有。在你的图中有更多的地形是没有问题的。如果这意味着一个包含多个部分的记录(您的示例),或者如果这是一对多关系(我的示例),或者它是多对多列出类型(ShipTo,BillTo等)。 )在连接表中。多对多确实减少了客户和各种ContactInfo类型之间的关系,但是当您需要具体的关系时,它会在场景的应用程序开发中创建开销。

+0

谢谢你的回答。我们坚持保存到数据库,尽管你是对的,我们可以将这个实现抽象出来并使用其他的东西,如缓存和序列化。为了简化持久性,我们使用反射将数据库列直接移动到属性,反之亦然。创建多层对象会更可取,但会使我们的ORM策略复杂化,因此我们正在使用接口。另外,我不明白具体类型如何解决我的问题不仅仅是接口?你会介意更多,因为我错过了它。 –

+1

@MarkRucker,实现从同一接口继承的两个接口肯定会在将对象映射到表时产生问题,并且接口不会序列化。而且,虽然界面很有价值,但它们不是替代良好阶层的替代品。如果您担心派生类型,不要害怕使用按表继承。 –