从字面意义上看来,享元就是共享一些元素。它解决的是一个轻量级的创建或拷贝。什么意思呢?
例如:我有一个用企业用户管理的功能模块,用户有名字,和公司的一些基本信息, 公司的信息是需要根据用户的名字到数据库中查询的。
class CompanyInfo
{
//公司名称
protected $_name;
//公司地址
protected $_addr;
//初始化
public function __construct($userName)
{
$result = $this->getInfoByUserName($userName);
$this->_name = $result['name'];
$this->_addr = $result['addr'];
}
//根据用户名到数据库中查询公司信息
public function getInfoByUserName($userName)
{
//返回查询结果,代码略
}
}
class User
{
protected $_name;
protected $_companyInfo;
//用户初始化
public function __construct($name)
{
$this->_name = $name;
$this->_companyInfo = new CompanyInfo($this->_name);
}
}
//创建用户
$andrew = new User('andrew');
$delia = new User('delia');
这样没什么问题,假设如果我们知道,andrew和delia都是同一个公司的人。那么他们的信息应该是一样的,就没必要重复从数据库中读取信息了。但名字可能不一样。那我们就把andrew对象复制一下,然后把名字改了不就行了嘛。嗯,很简单。那user对象就缺少一个设置名字的方法。
class User
{
protected $_name;
protected $_companyInfo;
//用户初始化
public function __construct($name)
{
$this->_name = $name;
$this->_companyInfo = new CompanyInfo($this->_name);
}
//设置名字
public function setName($name)
{
$this->_name = $name;
}
}
$andrew = new User('andrew');
$delia = clone $andrew;
$delia->setName('delia');
好了,这样,一个享元模式就完成了。什么?这么简单。对的,就是这么简单。在php中当复制一个对象时,它的companyInfo对象会复制一个引用。这样你就不用再从数据库中读取信息。直接两个人共享这一个信息就可以了。同时我们修改一下公司的信息,两个人都会发现改变。好,那我们试一下:
class CompanyInfo
{
//公司名称
protected $_name;
//公司地址
protected $_addr;
//初始化
public function __construct($userName)
{
$result = $this->getInfoByUserName($userName);
$this->_name = $result['name'];
$this->_addr = $result['addr'];
}
//根据用户名到数据库中查询公司信息,在这里我们假设了一个值
public function getInfoByUserName($userName)
{
return array(
'name' => 'qihoo',
'addr' => 'beijing',
);
}
//设置公司名
public function setName($name)
{
$this->_name = $name;
}
}
class User
{
protected $_name;
protected $_companyInfo;
//用户初始化
public function __construct($name)
{
$this->_name = $name;
$this->_companyInfo = new CompanyInfo($this->_name);
}
//设置名字
public function setName($name)
{
$this->_name = $name;
}
//获取公司信息
public function getCompanyInfo()
{
return $this->_companyInfo;
}
}
$andrew = new User('andrew');
$delia = clone $andrew;
$delia->setName('delia');
$andrew->getCompanyInfo()->setName('cc');
var_dump($andrew);
var_dump($delia);
输出结果如下:
object(User)#1 (2) {
["_name:protected"]=>
string(6) "andrew"
["_companyInfo:protected"]=>
object(CompanyInfo)#2 (2) {
["_name:protected"]=>
string(2) "cc"
["_addr:protected"]=>
string(7) "beijing"
}
}
object(User)#3 (2) {
["_name:protected"]=>
string(5) "delia"
["_companyInfo:protected"]=>
object(CompanyInfo)#2 (2) {
["_name:protected"]=>
string(2) "cc"
["_addr:protected"]=>
string(7) "beijing"
}
}
我们可以看到,andrew的名字发生改变后不会对delia这个用户的名字产生影响,但是,andrew的companyInfo发生改变后,两个都发生了改变。也就是说,andrew和delia共享了companyInfo.享元模式的目的在于,通过共享一些对象的公共数据,减少创建和复制所带来的性能消耗。