2010-10-19 40 views
11

Thẳng đến điểm: Tôi có hai lớp đơn, cả hai đều thừa hưởng bản chất đơn từ một lớp siêu hạng. Tôi khởi tạo một số thuộc tính trên singleton đầu tiên, và sau đó có singleton thứ hai lấy trường hợp đầu tiên. Ví dụ đó, tuy nhiên, dường như không phải là một trong những tôi khởi tạo ở nơi đầu tiên. Một số mã ví dụ có thể giúp giải thích này:Tạo một lớp cơ sở Singleton bằng PHP 5.3

Thứ nhất, siêu hạng, cung cấp chất singleton (yêu cầu PHP 5.3 hoặc cao hơn):

class Singleton { 

    protected static $instance; 

    protected function __construct() { } 

    final private function __clone() { } 

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

} 

Sau đó, chúng tôi đã có các singleton đầu tiên mang một giá trị :

require_once('Singleton.php'); 

class SingletonA extends Singleton { 

    protected $value; 

    public function SingletonA() { 
     $this->value = false; 
    } 

    public function getValue() { 
     return $this->value; 
    } 

    public function setValue($value) { 
     $this->value = $value; 
    } 

} 

Sau đó singleton thứ hai tham chiếu đến singleton đầu tiên:

require_once('Singleton.php'); 
require_once('SingletonA.php'); 

class SingletonB extends Singleton { 

    public function getValue() { 
     return SingletonA::getInstance()->getValue(); 
    } 

} 

Bây giờ cho các bài kiểm tra đó cho thấy cách này không thành công:

require_once('SingletonA.php'); 
require_once('SingletonB.php'); 

SingletonA::getInstance()->setValue(true); 

echo (SingletonA::getInstance()->getValue()) ? "true\n" : "false\n"; 
echo (SingletonB::getInstance()->getValue()) ? "true\n" : "false\n"; 

Xét nghiệm này mang lại kết quả như sau:

true 
false 

Rõ ràng, ví dụ SingletonA rằng mã kiểm tra tài liệu tham khảo không phải là trường hợp tương tự mà các SingletonB tham chiếu cá thể. Tóm lại, SingletonA không đơn độc như tôi cần. Sao có thể như thế được? Và tôi có thể sử dụng ma thuật nào để khắc phục hành vi này, cho tôi một singleton thực sự?

+1

Đây là lần đầu tiên tôi gặp phải hành vi Singleton được kế thừa. Cho dù nó có đúng cú pháp hay không, nó khá là lạ. – spender

+0

SingletonA sẽ không bao giờ là một ví dụ của SingletonB, mặc dù cả hai đều là Singletons; từ khóa 'static' sẽ đảm bảo điều đó. – thetaiko

+0

Tại sao không chỉ sử dụng Singleton? – Stephen

Trả lời

11

Hãy thử sử dụng isset hơn instanceof:

class Singleton { 
    protected static $instances; 

    protected function __construct() { } 

    final private function __clone() { } 

    public static function getInstance() { 
     $class = get_called_class(); 

     if (!isset(self::$instances[$class])) { 
      self::$instances[$class] = new $class; 
     } 
     return self::$instances[$class]; 
    } 
} 
+0

Cảm ơn lonesomeday, nhưng điều đó mang lại cho tôi ví dụ tương tự, đó không phải là những gì tôi muốn. –

+0

@Johan Bạn nói đúng, đúng vậy. Xin lỗi vì điều đó. Tôi đã viết lại lớp của bạn bằng cách sử dụng một mảng các cá thể trong 'Singleton :: $ instances', nó hoạt động. – lonesomeday

+0

Cảm ơn một triệu người! Phiên bản này thậm chí sẽ chạy trên các phiên bản PHP <5.3, theo như tôi thấy. Nhưng tôi vẫn không hiểu tại sao nó không hoạt động. –

0

Tôi khá chắc chắn đó là vì bạn đang sử dụng các phương pháp tĩnh, không được hỗ trợ.

0

SingletonASingletonB là các lớp khác nhau. Mặc dù chúng kế thừa từ cùng một lớp, chúng là các lớp riêng biệt và do đó chúng có các cá thể tĩnh khác nhau.

Nếu bạn thay đổi mã của mình để nhận 2 phiên bản SingletonA hoặc 2 phiên bản SingletonB, bạn sẽ thấy hành vi bạn mong đợi. Nhưng bởi vì họ là những lớp khác nhau, họ không phải là cùng một singleton.

0

Hãy OO nói chuyện. :)

SingletonASingletonB là loại Singleton

do đó có thể nói:

SingletonASingleton

SingletonBSingleton

ví dụ:họ cả Singleton

Ý nghĩa dự kiến ​​của Singleton có nghĩa là có thể chỉ có một. Nhiều người từ nền OO sử dụng mã của bạn sẽ bị nhầm lẫn.

Thông thường, việc thực hiện Singleton sẽ ở trên cơ sở mỗi lớp vì hầu hết các ngôn ngữ OO sẽ không bị uốn cong để cho phép ý định của những gì bạn đang đề xuất.

PHP đó có thể làm (thông qua get_called_class() phép thuật) không có nghĩa là phải.

Tôi hoàn toàn có thể chấp nhận điều đó từ quan điểm tiện dụng, câu trả lời được chấp nhận có vẻ tốt. Với sự tiện lợi của câu trả lời được chấp nhận, tôi đề xuất một thay đổi tên không xung đột với việc triển khai Singleton "chuẩn". Từ quan điểm của OO nghiêm ngặt, người ta không bao giờ có thể kế thừa từ Singleton, vì vậy nó thực sự cần một cái tên khác.

+0

Cảm ơn bạn đã dành thời gian trả lời một cách hào phóng. Tôi sẽ không đòi hỏi nhiều chuyên môn khi nói đến lý thuyết đằng sau mô hình singleton, nhưng trong khi tôi đồng ý SingletonA và SingletonB cả hai có thể được cho là trường hợp của Singleton, họ cũng là trường hợp của các loại khác nhau. Tôi đã không thể tìm thấy bất kỳ định nghĩa nào giải quyết khía cạnh thừa kế của mẫu, nhưng theo cách tôi thấy, nếu một khu rừng chỉ có thể giữ một con hổ và một con sư tử, chúng có thể cùng tồn tại ngay cả khi chúng cả hai felines.Một lần nữa, tôi tuyên bố không có kiến ​​thức lớn hơn này so với những cuộc tàn phá của riêng tôi. –

+0

Tôi biết những gì bạn có ý nghĩa ở đây, và tôi sẽ không thiết kế một cái gì đó với nhiều singletons anyway (Tôi muốn sử dụng nhiều nhất, và lưu trữ tất cả các trường hợp khác trong đó). Tôi đồng ý rằng sẽ tốt hơn (a) đổi tên lớp cơ sở thành 'BaseSingleton' hoặc tương tự. – lonesomeday

Các vấn đề liên quan