找回密码
 注册
搜索
热搜: 回贴
微赢网络技术论坛 门户 数据库 查看内容

在数据库中使用对象的好处

2009-12-14 18:26| 发布者: admin| 查看: 49| 评论: 0|原作者: 江海

●显而易见,这对我们控制存取对象的数据有很......


显而易见,这对我们控制存取对象的数据有很大帮助。如果一个程序员已经直接地存取username的信息,以上代码的变化将会破坏他的代码。然而我们可以使用(类的)存取方法,就像上面代码中注释的那样,添加一个验证的功能而不需要改变任何其他的东西。注意username的验证(例子当中是不能超过12字节)代码是独立在setUsername()方法之外的。从验证到存储到数据库的过程轻而易举。而且,这是个非常好的单凭经验的方法,一个方法或一个类需要做的越少,它的重复使用的机会将会越大。这在你开始写一个子类时更加明显,假如你需要一个子类,并且又要跳过(忽略)父类方法(行为)中的一些特殊的细节,如果(针对这个细节的)方法很小而又精细,(修改它)只是一瞬间的过程,而如果这个方法非常臃肿,针对多种目的,你可能将在复制子类中大量代码中郁闷而终。

比方说,假如Admin是User类的一个子类。我们对adamin的用户可能会有不同的,相对苛刻一些的密码验证方法。最好是跨过父类的验证方法和整个setUsername()方法(在子类中重写)。

更多关于存取器(Accessor)
下面是一些其他的例子来说明如何使存取器用的更有效果。很多时候我们可能要计算结果,而不是简单的返回数组中的静态数据。存取方法还能做的一个有用的事情就是更新(updating)缓存中的值。当所有的变动(对数据的所有操作)都要通过setX()方法的时候,这正是我们根据X来重置缓存中的值的时刻。

于是我们的这个类层次变得更加明了:
内部变量$_data的处理被替换成受保护的私有方法(private methods)_getData()和_setData()
这类方法被转移到被称作记录(Record)的抽象的超级类(super class),当然它是User类下的子类
这个记录类(Record class)掌握所有存取数组$_data的细节,在内容被修改之前调用验证的方法,以及将变更的通知发给记录(Records),就像发给中心对象存储(ObjectStore)实例。

class User extends Record {

// --- OMITTED CODE --- //

/**
* Do not show the actual password for the user, only some asterixes with the same strlen as the password value.
*/
function password() {
$passLength = strlen($this->_getData('password'));
return str_repeat('*', $passLength);
}
/**
* Setting the user password is not affected.
*/
function setPassword($newPassword) {
$this->_setData('password', $newPassword);
}

/**
* fullName is a derived attribute from firstName and lastName
* and does not need to be stored as a variable.
* It is therefore read-only, and has no 'setFullname()' accessor method.
*/
function fullName() {
return $this->firstName() . " " . $this->lastName();
}

/**
* Spending limit returns the currency value of the user's spending limit.
* This value is stored as an INT in the database, eliminating the need
* for more expensive DECIMAL or DOUBLE column types.
*/
function spendingLimit() {
return $this->_getData('spendingLimit') / 100;
}

/**
* The set accessor multiplies the currency value by 100, so it can be stored in the database again
* as an INT value.
*/
function setSpendingLimit($newSpendLimit) {
$this->_setData('spendingLimit', $newSpendLimit * 100);
}

/**
* The validateSpendingLimit is not called in this class, but is called automatically by the _setData() method
* in the Record superclass, which in turn is called by the setSpendingLimit() method.
*/
function validateSpendingLimit(&$someLimit) {
if (is_numeric($someLimit) AND $someLimit >= 0) {
return true;
} else {
throw new Exception("Spending limit must be a non-negative integer"); //PHP5 only
}
}
}

/**
* Record is the superclass for all database objects.
*/
abstract class Record {
var $_data = array();
var $_modifiedKeys = array(); // keeps track of which fields have changed since record was created/fetched

/**
* Returns an element from the $_data associative array.
*/
function _getData($attributeName) {
return $this->_data[$attributeName];
}

/**
* If the supplied value passes validation, this
* sets the value in the $_data associative array.
*/
function _setData($attributeName, $value) {
if ($this->validateAttribute($attributeName, $value)) {
if ($value != $this->_data[$attributeName]) {
$this->_data[$attributeName] = $value;
$this->_modifiedKeys[] = $attributeName;
$this->didChange();
} else {
// the new value is identical to the current one
// no change necessary
}
}
}

/**
* For an attribute named "foo", this looks for a method named "validateFoo()"
* and calls it if it exists. Otherwise this returns true (meaning validation passed).
*/
function validateAttribute($attributeName, &$value) {
$methodName = 'validate' . $attributeName;
if (method_exists($this, $methodName)) {
return $this->$methodName($value);
} else {
return true;
}
}

function didChange() {
// notify the objectStore that this record changed
}
}
?>


现在我们拥有了一个抽象的超级类(Record),我们可以将User类里面大量的代码转移出来,而让这个User的子类来关注User的特殊项目如存取和验证方法。你可能已经注意到在我们的这个纪录类(Record class)没有任何的SQL代码。这并不是疏忽或者遗漏!对象存储类(ObjectStore class)(隐藏在第二部分)将负责所有和数据库的交互,还有我们的超级类Record的实例化。这样使我们的Record类更加瘦小而又有效率,而这对于评价我们处理大量对象的效率的时候是个重要因素。

如果你有兴趣看看这篇文章基于的完整的代码(不会出现如文中出现的所有的语法错误),可以给我的邮箱发信

最新评论

QQ|小黑屋|最新主题|手机版|微赢网络技术论坛 ( 苏ICP备08020429号 )

GMT+8, 2024-9-29 15:32 , Processed in 0.082657 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

返回顶部