我已经看到了在数据库之间来回加载对象的不同方法,有两个常见的方法,如下所示。哪一个更好,为什么?
方法1:这包括为类load(id)
和save()
定义两个成员方法。这些方法在类的实例上调用。例如,
class Wheel{
double diameter;
string tag;
public void Load(int id){
var result = ... // database query
this.diameter = result['diameter'];
this.tag = result['tag'];
}
public void Save(){
... // database query to update row
}
}
Wheel johnWheel = new Wheel();
johnWheel.Load(5); // In this case John's wheel has a row id of 5 in the database
方法2:直接加载/保存对象的实用程序方法:
class DBUtils{
public static Wheel LoadWheel(int id){
var result = ... // database query
Wheel w = new Wheel();
w.setDiameter(result['diameter']);
w.setTag(result['tag']);
}
public static void SaveWheel(Wheel wheel){
...// Update DB
}
}
我问,因为轮子的概念是什么?本身不包括从数据库加载和保存它的函数,因此方法1 可能被认为是错误的OOP设计。
答案 0 :(得分:1)
您应该创建一个单独的类来处理数据库连接以及这些连接的创建/销毁。这样,wheel
就是它正在使用的数据库的独立实体。
使用方法2。
答案 1 :(得分:1)
两者看起来都有点......
方法1
首先,Load()
在这种情况下应该是静态工厂。这种用法有点迟钝:
Wheel johnWheel = new Wheel();
johnWheel.Load(5);
在这两行代码之间,johnWheel
是什么?是否接近有效状态?如果没有,那么它的构造似乎有点破碎。 OO原则建议将其封装到单个操作中,而不是期望消耗代码每次执行多个顺序操作。如果它是静态工厂,则使用更简单:
Wheel johnWheel = Wheel.Load(5);
方法2
这个更像是一个命名问题而不是结构问题。 DBUtils
?这将成为快速无关功能的倾销场。你想避免这种情况。这样的事情怎么样?:
class WheelRepository
{
public static Wheel Get(int id)
{
// ...
}
public static void Save(Wheel wheel)
{
// ....
}
}
作为对象(毕竟这仍然是OOP),WheelRepository
代表(因此封装)非常具体的功能,而DBUtils
则不代表。
<强>结论强>
我通常更喜欢结构意义上的方法2,因为业务对象(Wheel
)不应该知道关于数据库的任何内容({{1 }})。前者是核心便携式业务问题,后者是外围基础设施问题。我唯一需要注意的是,我建议使用标准模式来改进方法2,例如存储库模式和工作单元模式的组合。
答案 2 :(得分:0)
我会选择方法2(就像laiello提出的那样)。然而,我不会将类命名为DbUtils,而是更像WheelDao或WheelRepository(例如,如果您的Wheel类是域模型中的Root实体)。
但是,如果使用方法1,则load(id)方法应该是静态的。因为它不是在对象的特定实例上调用,而是生成对象的新实例。这与save()方法不同,在特定的Wheel实例上调用它是正确的。