2013-03-30 21 views
0

我有一个数据库,其中包含“小部件”,比方说。例如,小部件具有诸如“长度”和“宽度”等属性。用于创建wdigets的原始低级API是一团糟,所以我正在编写一个更高级别的函数集以使调用者更容易。数据库很奇怪,我不能很好地控制创建widget对象的时间。具体来说,直到处理的后期阶段,以及某些其他事情先发生之后才能创建。但是,我希望我的呼叫者认为在早期阶段已创建了一个窗口小部件对象,以便他们可以从一开始就获取/设置其属性。代理对象来模拟即将创建的数据库

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

  • 如果相应的控件对象在数据库中已存在,则设置 其Width属性
  • 如果不是,存储给定宽度值在private_Width字段中供以后使用。

在稍后的阶段,当我确信窗口小部件对象已经在数据库中创建时,我复制所有值:从private_Width复制到数据库宽度字段等等(一个字段/属性不幸的是)。

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

+0

当您在数据库中创建窗口小部件时,您有任何通知?否则,你怎么知道你什么时候可以保存你的缓冲变化? – stakx

+0

不是真的“通知”,但有一个功能,我可以打电话找出小部件是否存在于数据库中,并且有一个时间点我确定它存在,甚至没有问。在后面的时间点,我保存缓冲的数据。 – bubba

回答

1

首先,以我的经验,手工编码的数据访问层可以感觉像很多重复性的工作(投入到位的ORM,如NHibernate的或实体框架,威力有所缓解这个问题),并更新旧数据访问层糟糕的工作,特别是当它由许多部分组成时。

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

  • 你可以建立ProxyWidget无论是作为Widget替代实现(或者从现有的低级API的widget类的叫法),也可以实现它“在...之上“,或作为”包装物“,Widget。这是Adapter design pattern

    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 design pattern一个例子。

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

+0

感谢您的想法。就像你描述的那样,我的高级NewWidget确实是一个OldWidget的包装。我无法更改实现OldWidget的代码,因此无法从同一接口继承OldWidget和NewWidget,我可以吗?如果可以的话,这将是很好的/自然的 - 它们的属性几乎完全相同。 T4文本模板很有趣。我使用类似的想法来编写原始代码,除了我使用了Excel和宏。所以,我没有亲手写代码,但我仍然不自觉 - 15000行重复的喋喋不休,经常需要更新。 – bubba

+0

** 1。** T4很不错,因为它与Visual Studio和构建系统相集成得很好。但我不是推销员 - 这只是一种可能性,不要盲目地遵循我的建议。 ** 2。**不,您无法将界面添加到现有类型。你只能创建一个新的包装类型并在那里实现接口。 – stakx