2013-02-04 105 views
3

使用单例模式时是否存在差异?在类中保存静态实例并将其保存在返回实例的方法中时是否有任何区别?在类方法中使用静态实例还是在类中使用

例子: 课内。

class cExampleA { 
    static $mInstance; 

    protected function __construct() { 
     /* Protected so only the class can instantiate. */ 
    } 

    static public function GetInstance() { 
     return (is_object(self::$mInstance) ? self::$mInstance : self::$mInstance = new self()); 
    } 
} 

返回方法里面。

class cExampleB { 
    protected function __construct() { 
     /* Protected so only the class can instantiate. */ 
    } 

    static public function GetInstance() { 
     static $smInstance; 
     return (is_object($smInstance) ? $smInstance : $smInstance = new self()); 
    } 
} 

在一个侧面说明,使用三元运算符的例子有效(这意味着它可能会导致问题),并没有任何好处/倒台使用is_object超过isset?

更新:似乎唯一的区别是静态实例的范围?

+0

,在跳出我这里的是,在照例a,静态属性是公开访问的主要事情。我猜这不是你想要的,所以你应该把它设置为'private'(尤其是因为你只用'is_object()'来检查它,这意味着它可以被任何东西覆盖。会更安全)。 – SDC

+0

是的,我刚刚错过了私人。 instanceof听起来像个好主意,我总是忘记它。 – James

+0

我必须说实话,我不知道在这种情况下是有区别的。我想这是其中有不止一种方法来实现同样的事情的情况之一。除非有人能以其他方式告诉我一个理由。对我来说,我会坚持使用私有财产(即exampleA),但我看不出为什么exampleB是错误的任何理由。 – SDC

回答

1

有趣的问题。就行为而言,据我所知,这两个例子之间没有任何区别(范围除外)。

PHP是一种松散类型的编程语言,因此您甚至可以在示例A中全部省略类属性声明。而对于松散类型的语言,似乎总有更多的方法实现相同的功能!

真正的问题很快就会变成设计模式之一(在这种情况下是数据封装),以确保我们编写的代码遵循由我更聪明的人设计的惯例!

在这个例子中,类应该拥有它的属性,并适当地设置该属性的范围(在这种情况下是私有的)并提供逻辑存取方法。

这是我会怎么写呢:

class ExampleA 
{ 
    static private $_instance = null; 

    private function __construct(){} 

    static public function getInstance() 
    { 
     if (!self::$_instance instanceof self) { 
      self::$_instance = new self(); 
     } 

     return self::$_instance; 
    } 
} 

如果你要封闭方法本身的变量,严格来说,它不会是一个类属性。另外,你会失去一点可读性,其他开发者(不习惯例B的设计模式)会寻找类属性声明,而不是通过类方法进行挖掘。

+0

感谢你的意见。我从可读性的角度理解你的观点,但似乎没有任何技术上的观点可以说明你的观点。在旁注中,我没有使用匈牙利符号,前缀与范围不相关于变量类型。 – James

0

是否有类持有的静态实例,并拿着它在返回实例的方法时,有什么区别?

没有,有在功能上没有区别,授予你修改静态实例属性的知名度,保护或私有:

class cExampleA { 
    protected static $instance = null; 
    // ... 
} 

顺便说一句,不要使用符号,如$mInstance;现在你不需要那些拐杖

另外,看到你如何设置构造函数为受保护的可见性,我假设你想能够在稍后扩展类?在这种情况下,你需要改变getInstance()方法:

public final static function GetInstance() 
{ 
    if (self::$instance === null) { 
     self::$instance = new static; 
    } 
    return self::$instance; 
} 

否则,你的构造应该仅仅是私人,这样就可以再次使用new self;

+0

我从未见过之前使用过的'新静态'。通常,当我想扩展这个类时,我使用了不同的方法,这取决于实例将如何使用。在附注中,我经常收到关于我的编码风格的评论。大多数人认为这不是匈牙利符号,而是防止命名冲突的范围指标。 – James

+0

@James yep这是迟到的静态绑定:) –

相关问题