我正在做一个“容器”类来保存我的所有模型/服务实例,该类是一个单例。
考虑以下代码部分(来自CodeIgniter项目):
public function getReviewModel()
{
static $loaded = false;
if (!$loaded)
{
$this->load->model('review_model');
$loaded = true;
}
return $this->review_model;
}
我想知道是否仍然可以使用这样的静态内部方法,或者我应该只使用类属性(我的意思是性能和编码标准)?
答案 0 :(得分:2)
在你的例子中,没有什么能阻止程序员多次实例化这个类(带有可怕的结果),所以这是一个令人困惑的代码。
静态变量有其用途,可以是函数的局部变量,也可以是类级定义的
特别是在PHP脚本中,当输出通常是单个数据时,可以方便地作为仅定义静态属性和方法的类来处理。
那将是一个真正的,万无一失的单身人士课程。
由于将静态变量误认为动态变量是一个常见的陷阱,我倾向于偏向静态类变量以避免混淆(即self::$...
语法使它们清楚地突出)。
答案 1 :(得分:1)
就PHP中的静态问题而言,普遍的共识是:尽可能避免。是的,99%的情况下,可以避免静力学
应该百分之百地避免单身人士。 For reasons you can find here以及网络上的其他任何地方。单身人士就像共产主义一样:听起来很不错,但是当进行练习时,事实证明你有一两件事没有预料到。
Singletons的主要目标是保留状态,但PHP本身是无状态的,所以在下一个请求中,单例需要重新初始化。
如果我像你一样写吸气剂,我倾向于以一种懒惰的方式创造它们:
class Example
{
private $reviewModel = null;//create property
public function getReviewModel()
{
if ($this->reviewModel === null)
{//load once the method is called, the first time
$this->reviewModel = $this->load->model('review_model');
}
return $this->reviewModel;
}
}
这基本上做同样的事情,不使用静态。因为我正在使用属性,所以我仍然保留实例,因此如果再次调用getReviewModel
方法,则会跳过load->model
调用,就像使用静态一样。
但是,由于您要询问性能以及编码标准:静态比实例属性稍微慢一些:每个实例都有一个包含其属性的HashTable和一个指向其定义的指针。静态驻留在后者中,因为它们由所有实例共享,因此静态属性需要额外的查找工作:
instance -> HashTable -> property
instance -> definition -> HashTable -> property
这不是完整的故事,check answer + links here,但基本上:通往静态的路线更长。
至于编码标准:它们存在,虽然仍然是非正式的,但大多数主要参与者都订阅它们,所以你应该这样:PHP-FIG
像$this->_protectedProperty;
之类的东西不符合PSR-2标准,例如,它非常明确地指出:
属性名称不应以单个下划线为前缀,以表示受保护或隐私可见性。