从数据库加载 - 在课堂内外?

时间:2014-12-16 19:48:32

标签: oop

我已经看到了在数据库之间来回加载对象的不同方法,有两个常见的方法,如下所示。哪一个更好,为什么?

方法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设计。

3 个答案:

答案 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实例上调用它是正确的。