我有一个名为DatabaseRow
的抽象类,在派生和构造之后,主要从Load(object id)
方法加载。
我有很多代码可以创建类的新实例,从ID加载它,然后返回类。我想将这段代码简化为一行代码(只是为了整洁,有很多类只有具有返回这些Loaded实例的属性列表)。
我可以通过两种方式来做这件事,但对我来说似乎都不对。
1。我可以在return this;
方法结束后Load
使用return new Derived().Load(id);
2. 我可以创建一个通用方法来返回一个加载的方法。
public static T LoadRow<T>(object id) where T : DatabaseRow, new()
{
T row = new T();
row.Load(id);
return row;
}
我见过其他一些使用与 1 相同的方法的代码,但我从未见过任何有经验的开发人员推荐它,也没有遇到.NET框架中的任何方法做同样的事情,所以也许这不是最佳做法?
是否有人知道其他任何可能比这两种解决方案都更好的解决方案?
解决方案:
在阅读SirViver的回答和评论之后,我意识到所有返回的属性都需要缓存。解决方案有点不同,但类似于选项 2 (我不希望任何人提出这个答案,因为我没有解释这部分设计)
所有这些实例都将从数据库中另一列检索的值(如果您愿意,数据库关系)中加载。我没有尝试从这个值加载新实例,而是创建了一个从列名加载实例并将加载的值缓存到Dictionary中的方法。这很有效,因为这是DatabaseRow
类的主要功能之一。
private Dictionary<string, DatabaseRow> linkedRows;
protected T GetLinkedRow<T>(string key) where T : DatabaseRow, new()
{
if (linkedRows.ContainsKey(key)) return (T)linkedRows[key];
else
{
T row = new T();
row.Load(this[key]);
linkedRows.Add(key, row);
return row;
}
}
答案 0 :(得分:3)
就个人而言,我认为链接对象实例具有实际副作用的方法调用是不好的做法。说实话,我认为这两个例子都是非常丑陋的“黑客”,其唯一目的是节省两行代码。我不认为结果实际上更具可读性。
如果你想立即加载一条记录,我可能宁愿提供一个构造函数变体来获取你加载的ID,并使该对象在构造时自动填充,但是当我想到它时,我不会'实在是太麻烦了 - 在一行中填充更多信息并不能提供更多可读和可维护的代码。
答案 1 :(得分:2)
第一名在某些圈子中越来越受欢迎;当有一个接口定义了大量的这些方法并且可以组装长链时,它通常被称为流畅的编程。成功完成此操作的关键是永远不要定义有时返回this
的方法,但有时会返回null
。如果总是返回this
(除非有例外),那就是非常好的风格。
我个人并不喜欢像2号这样的解决方案,因为可以说它违反了“一个责任”的原则。
答案 2 :(得分:1)
只有在没有加载的情况下才能使用选项1。这是由于允许您执行此操作的模式:
return new Derived();
我个人更喜欢静态方法。但我怀疑这只是个人偏好的问题。
正如ssg所说的另一个选项(让我们称之为选项3)是重载Derived中的构造函数也可以工作,但是有很多构造函数通常会让人困惑,因为调用代码中没有任何东西可以解释什么正在继续。
选项1:
return new Derived().Load(10);
选项2:
return Derived.Load(10);
选项3:
return new Derived(10);
选项1看起来像是在创建一个多余的对象。选项2很好,因为它做了它看起来正在做的事情。备选方案3对它的作用感到困惑。
答案 3 :(得分:0)
虽然我个人喜欢返回this
的方法,因为它允许它们被链接,但我认为在.NET框架中(直到Linq),这是不受欢迎的。想到这一点的原因是:
方法返回结果或更改对象的状态。返回this
有两点:更改对象的状态然后返回“结果” - 除了结果是修改后的原始对象。这不符合用户的期望。
怎么样:
public class Derived : DatabaseRow
{
public Derived(object id):
{
Load(id);
}
}
并像这样使用它:
return new Derived(id);