0

比方说,我有一个包含“小部件”的数据库。例如,小部件具有长度和宽度等属性。用于创建 wdigets 的原始低级 API 是一团糟,所以我正在编写一组更高级别的函数来让调用者更轻松。数据库很奇怪,我无法很好地控制小部件对象的创建时间。具体来说,直到处理的后期阶段,在某些其他事情首先发生之后,才能创建它。但我希望我的调用者认为小部件对象已在较早阶段创建,以便他们可以从一开始就获取/设置其属性。

因此,我实现了一个调用者可以使用的“ProxyWidget”对象。它有 private_Length 和 private_Width 等私有字段,可以存储所需的值。然后,它还具有我的调用者可以访问的公共属性 Length 和 Width。如果调用者告诉我设置 Width 属性的值,逻辑是:

  • 如果对应的widget对象已经存在于数据库中,则设置其Width属性
  • 如果没有,请将给定的宽度值存储在 private_Width 字段中以供以后使用。

在稍后的某个阶段,当我确定已在数据库中创建了小部件对象时,我会复制所有值:从 private_Width 复制到数据库 Width 字段,依此类推(不幸的是,一次只有一个字段/属性) .

这适用于一种类型的小部件。但是我有大约 50 种类型,每种类型都有大约 20 个不同的字段/属性,这会导致无法维护的混乱。我想知道是否有更聪明的方法。也许我可以使用反射来创建“代理”对象并以通用方式复制字段/属性数据,而不是编写大量重复代码?以某种方式分解出通用代码?我可以从“数据绑定”模式中学到什么吗?我是一名数学家,而不是程序员,我有一种不安的感觉,即我目前的方法简直是愚蠢的。我的代码在 C# 中。

4

1 回答 1

1

首先,根据我的经验,手动编写数据访问层可能会感觉像很多重复性工作(放置 ORM,例如 NHibernate 或实体框架,可能会在一定程度上缓解这个问题),并且更新遗留数据访问层非常糟糕工作,特别是当它由许多部分组成时。

您的问题中有些事情不清楚,但我想仍然可以给出高层次的答案。这些是为了给你一些想法:

  • 您可以将其构建ProxyWidgetWidget(或调用现有低级 API 中的任何小部件类)的替代实现,或者您可以“在上面”实现它,或者作为“包装器”来实现,Widget. 这就是适配器设计模式

    public sealed class ExistingTerribleWidget { … }
    
    public sealed class ShinyWidget // this is the wrapper that sits on top of the above
    {
        public ShinyWidget(ExistingTerribleWidget underlying) { … }
        private ExistingTerribleWidget underlying;
        … // perform all real work by delegating to `underlying` as appropriate  
    }
    

    我建议(至少在仍有代码使用现有低级 API 的情况下)您使用这种模式而不是创建一个完全独立的Widget实现,因为如果数据库模式发生更改,您将不得不更新两个不同的 API . 如果您将新EasyWidget类构建为现有 API 之上的包装器,则它可能保持不变,只需更新底层实现。

  • 您描述ProxyWidget了两个功能(1)允许修改已经持久化的小部件;(2) 新小部件的缓冲区,稍后将添加到数据库中。

    如果您有一种通用的基本类型和两个子类,您或许可以简化您的设计:一种用于尚未持久化的新小部件,另一种用于已持久化的小部件。后一种子类型可能有一个额外的数据库ID属性,以便可以在数据库中识别、加载、修改和更新现有的小部件:

    interface IWidget { /* define all the properties required for a widget */ }
    
    interface IWidgetTemplate : IWidget
    {
        IPersistedWidget Create();
        bool TryLoadFrom(IWidgetRepository repository, out IPersistedWidget matching);
    }
    
    interface IPersistedWidget : IWidget
    {
        Guid Id { get; }
        void SaveChanges();
    }
    

    这是Builder 设计模式的一个例子。

  • 如果您需要为许多类(例如,您的 50 多种数据库对象类型)编写类似的代码,您可以考虑使用T4 文本模板。这只会减少编写代码的重复性;但是你仍然需要在某个地方定义你的 50 多个对象。

于 2013-03-30T11:12:27.390 回答