2010-01-20 38 views
10

Tôi hiện đang làm việc với các lớp và đối tượng PHP. Trong câu hỏi này, tên của các trường và phương thức được tạo ra chỉ để bạn có được một ý tưởng về những gì tôi đang nói đến.Mẫu đăng ký hoặc Singleton trong PHP?

Nó liên quan đến việc sử dụng các mẫu thiết kế đơn và đăng ký.

Bây giờ cho phép nói rằng tôi cần truy cập đối tượng Cơ sở dữ liệu, đối tượng bộ nhớ cache, đối tượng cài đặt lõi, đối tượng phiên trong hầu hết các lớp khác tôi sẽ cần có quyền truy cập vào các mục này. Vì vậy, tôi sẽ sử dụng một đăng ký để lưu trữ tất cả 4 của những đối tượng vào 1 đối tượng lớp đăng ký. Tôi có thể easiyl chỉ cần vượt qua trong đối tượng 1 của tôi vào bất kỳ đối tượng nào khác cần truy cập chúng. Vì vậy, âm thanh tuyệt vời cho đến nay nhưng nếu tôi có một số lớp mà không cần tất cả 4 của những đối tượng, nếu tôi CHỈ cần truy cập vào đối tượng Cơ sở dữ liệu hoặc đối tượng Phiên trong một số lớp khác của tôi? Đối với perfromance nó sẽ là tốt nhất để chỉ cần sử dụng một singleton bên trong các đối tượng khác hoặc nó sẽ giống nhau để đi trước và sử dụng đăng ký của tôi trong những?

Tôi không biết đủ về cách các đối tượng hoạt động trong PHP để biết liệu có bất kỳ loại tăng hiệu năng nào không (sử dụng ít bộ nhớ, sử dụng CPU, thời gian tải). Vì vậy, bất cứ ai có kinh nghiệm trong điều này có thể cho tôi biết nếu có bất kỳ lợi ích nào bằng cách sử dụng cái này hay cái kia, tôi đang ở giai đoạn mà tôi có thể đi ầm ĩ mà không ảnh hưởng đến thời gian sản xuất hay bất cứ thứ gì. Tôi muốn sử dụng phương pháp tốt nhất nếu tôi có thể.

+0

Tôi thực sự tìm thấy một câu hỏi chỉ bây giờ mà là cơ bản giống nhau http://stackoverflow.com/questions/1967363/registry-or-singleton – JasonDavis

+0

Hãy lưu ý nếu bạn đang sử dụng PHP4 hoặc PHP5 ... đối tượng hoạt động rất khác và trong các từ khóa PHP4 như 'tĩnh' không được hỗ trợ. Có thể bạn đang sử dụng 5, nhưng nếu bạn muốn tham gia OOP liên quan, bạn cần chắc chắn. –

Trả lời

3

Điều đó tùy thuộc vào ứng dụng của bạn. Nếu bạn vẫn cần 3 trong số 4 lớp, thì sẽ là lý tưởng hơn khi sử dụng Registry hơn là xử lý 3 cách độc lập chỉ vì bạn không cần thứ tư. Tải các lớp lazily sẽ là một cách tiếp cận để giảm bớt dấu chân bộ nhớ, nhưng sau đó bạn cần phải hướng dẫn đăng ký khi tạo các đối tượng và điều đó không khác nhiều so với việc xử lý các tệp đơn. Ngoài ra, bạn có thể tạo một hàm tạo tham số n hoặc sử dụng một mảng để chỉ thị cho Registry của bạn lớp nào cần khởi tạo trong khi xây dựng.

class Registry { 
    public $class1; 
    public $class2; 

    function __construct($uses) { 
     foreach($uses as $class) { 
      $this->{$class} = new {$class}(); 
     } 
    } 

} 

Sau đó, khởi tạo Registry của bạn bằng cách chỉ định lớp nào sẽ khởi tạo.

$reg = new Registry(array('class1')); 

Bạn rõ ràng là muốn hàm tạo của bạn xử lý các tham số bằng không để giải thích cho việc khởi tạo tất cả các lớp theo mặc định.

+0

Đó là một ý tưởng tuyệt vời, cảm ơn. Tôi nên đề cập đến, ngay cả khi 1 lớp chỉ cần 1-2 của các đối tượng, đã có một lớp khác được gọi trên cùng một trang có nhiều khả năng cũng sẽ có tất cả 4 đối tượng đã được tiêm vào nó. Tôi không chắc chắn như thế nào các công cụ bộ nhớ weorks mặc dù vậy nó có thể đã được tải 1 thời gian. Tôi không biết nếu bộ nhớ sẽ lưu trữ các đối tượng nhiều hơn thì một lần trong ram hay không. – JasonDavis

+0

Ví dụ mã của tôi giả định rằng các lớp của bạn được giữ trong bản sao Registry của riêng bạn. Điều này có nghĩa là rất nhiều bộ nhớ dư thừa nếu bạn có nhiều hơn một lớp trên mỗi trang sử dụng cùng một đối tượng Registry phổ biến. Nếu bạn đang sử dụng một cá thể tĩnh/toàn cầu, thì việc triển khai của bạn sẽ khác với ví dụ của tôi nhưng nó vẫn có thể được thực hiện. Điều này cũng có nghĩa là chia sẻ cùng một đối tượng trong bộ nhớ trên tất cả các lớp, điều này sẽ hiệu quả hơn nhiều. Để lấy ví dụ của tôi để làm việc theo cách đó, hãy tạo một hàm Registry :: initInstances() thay vì sử dụng hàm tạo. –

+0

Ok thats những gì tôi đã suy nghĩ, đoán chúng tôi đang trên cùng một trang, loại giống như phương pháp từ dbemerlin dưới đây. – JasonDavis

4

Bạn có thể thực hiện tải lười biếng để chỉ tải các đối tượng bạn thực sự cần:

class Registry 
{ 
    private static $database = null; 

    private static function connectDatabase($key) 
    { 
     [... do connection stuff ...] 
    } 

    public static function getDatabase($key) 
    { 
     if (Registry::$database == null) 
     { 
      Registry::connectDatabase($key); 
     } 
     return Registry::$database; 
    } 
} 

Mã đăng ký các thông số kết nối cơ sở dữ liệu là trái như tập thể dục cho người đọc.

+3

Đây không phải chỉ là một singleton? – JasonDavis

+0

Tôi không biết những gì khác có thể được gọi là singleton –

+0

Đây là mẫu đơn thuần túy, đó không phải là thực sự mô hình, mà là chống mẫu. –

1

Có lẽ đây là mẫu Singleton-Registry thích hợp. OFC, bạn có thể thực hiện những thứ khác nhau, giao diện SplFixedArray, ArrayAccess và các thứ khác. Ngoài ra nó không phải là xấu để thêm các destruct và phá hủy các đối tượng bên trong để đảm bảo không có rò rỉ có thể.

class oRegistry{ 
    private static $instance = null; 

    private $storage = array(); 

    private function __construct(){} 

    private function __clone(){} 

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

    public function attach($name, $o) { 
     if(true === isset($this->storage[$name])) { 
      throw new Exception('The instance with name '.$name.' already exists in registry.'); 
     } 
     if(!empty($name)) { 
      $this->storage[ $name ] = $o; 
     } 
    } 

    public function detach($name){ 
     if(isset($this->storage[ $name ])) { 
      $this->storage[ $name ] = null; 
      unset($this->storage[ $name ]); 
     } 
    } 

    public function get($name){ 
     if(false === isset($this->storage[$name])) { 
      throw new Exception('Invalid instance requested'); 
     } 
     return $this->storage[ $name ]; 
    } 
} 

// usage example 
$storage = oRegistry::getInstance(); 
$obj = new stdClass; 
$obj2 = new stdClass; 
$obj->test1 = 'test'; 
$obj2->test2 = 't2'; 

$storage->attach('test1', $obj); 
$storage->attach('test2', $obj2); 

$got = $storage->get('test2'); 
var_dump($got); // object(stdClass)#3 (1) { ["test2"]=> string(2) "t2" } 

$storage->detach('test2'); 
$got = $storage->get('test2'); 
var_dump($got); // bool(false) 
Các vấn đề liên quan