这更像是一个面向模式的问题,而不是语言特定的问题。假设我有一个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
的属性似乎反直觉,但我看到它的位置。这一切都重要吗?是否有适当的,纯粹的方式来做到这一点?
答案 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)
这种关注点分离将您的域对象(实体)与持久性机制的细节性细节隔离开来。这可以使您切换到不同的持久性提供程序,甚至可以并行使用多个持久性机制,而无需触及域对象。 (好吧,在实践中并不总是如此清晰,但这通常是朝着正确方向迈出的一步。)