持久化模型对象的模式?

时间:2012-03-09 20:06:04

标签: design-patterns

这更像是一个面向模式的问题,而不是语言特定的问题。假设我有一个User对象,其格式为:

class User
    var id
    var email
    var password
    var dateCreated
end

我见过两种常见的持久化User对象的方法如下:

// Approach 1
new User(id)
    ->setEmail(email)
    ->setPassword(pass)
    ->setDateCreated(date)
    ->saveNew()

在这种方法中,User对象具有每个属性集,然后saveNew方法将构建正确的insert语句,以使用在User上设置的属性在数据库上执行(例如,{{1另一种方法:

insert into user values (this.email, ...)

在这个例子中,您看到save方法虽然是一个实例方法,但却被视为一种静态方法,因为它正在传递一个填充的User对象,而不是处理它自己的数据,而这些数据依次构建正确的陈述(例如,// Approach 2 new User()->saveNew(User userObj) )。

对我来说,第二种方法感觉有点不对劲。但是,这就是我问你的原因。作为延续,让我问你一个类似的问题。比方说,我们想要获取用户。我们可以做以下事情:

insert into user values (user.email, ...) - 或 - new User(id)->fetch

现在,在fetch方法中,我已经看到了这两种方法:

new User()->fetch(id)

- 和 -

function fetch
    result = db->fetch('select * from user where id=this.id')

    user = new User()
    user->setId(result->id)
    user->setEmail(result->email)
    user->setPassword(result->password)
    user->setDateCreated(result->dateCreated)

    return user
end

返回一个新的User对象而不是设置function fetch result = db->fetch('select * from user where id=this.id') // We can set the properties directly or through their 'setters' this->id = result->id this->email = result->email this->password = result->password this->dateCreated = result->dateCreated return this end 的属性似乎反直觉,但我看到它的位置。这一切都重要吗?是否有适当的,纯粹的方式来做到这一点?

1 个答案:

答案 0 :(得分:0)

第二种方法对我来说并没有什么不妥。如果一个方法像静态方法一样使用,它应该是一个静态方法,句点。创建一个类的实例,其唯一目的是能够在其上调用一个成员方法,它实际上是作为一个参数传递给另一个完全不相关的类实例,它是恕我直言,丑陋,浪费,同时难以阅读时间。

OTOH通常不是最好的想法让班级承担坚持自己的责任(除了小而简单的系统)。这种方法不能扩展。如果您的持久性逻辑遍布整个地方,如果需要迁移到不同的数据库,它将变成一场噩梦。持久性是与表示用户的想法正交的概念,因此最好在不同的类中处理它。这类通常称为Data Access Objects (DAO)。使用DAO可能如下所示:

dao = new UserDAO()
...
user = new User(id)
user->setEmail(email)
user->setPassword(pass)
user->setDateCreated(date)
dao->save(user)

...

user2 = dao->fetch(id2)

这种关注点分离将您的域对象(实体)与持久性机制的细节性细节隔离开来。这可以使您切换到不同的持久性提供程序,甚至可以并行使用多个持久性机制,而无需触及域对象。 (好吧,在实践中并不总是如此清晰,但这通常是朝着正确方向迈出的一步。)