設計模式 - 關於PHP單例模式,有一點不明白,求指教!

來源:互聯網
上載者:User
首先,我定義個類,實現單例模式:(這裡是簡單一寫,就是個最基本的單例)

class Demo{    public static $instance;        private function __Construct()    {        //TODO    }        public static function getInstance()    {        if(!self::$instance){            self::$instance = new static();        }                return self::$instance;    }        public function call()    {        //其他方法    }}

下面有兩種方式執行個體化類:

1.在需要用的地方

$aa = Demo::getInstance();$bb = Demo::getInstance();$cc = Demo::getInstance();

這樣調用肯定是沒問題的,一般情況也是這樣初始化。

2.定義一個普通類,寫個函數初始化,儲存在一個靜態變數,如下:

類:

class Demo{    public function __Construct(){        //TODO    }}

函數:

function get_obj(){    static $obj;    if($obj){        return $obj;    }else{        $obj = new Demo;        return $obj;    }}

在需要調用的地方這樣寫:

$obj = get_obj();$obj->call();$obj2 = get_obj();$obj2->call();$obj3 = get_obj();$obj3 = get_obj();

這樣不是也只執行個體化一次這個類嗎?

回複內容:

首先,我定義個類,實現單例模式:(這裡是簡單一寫,就是個最基本的單例)

class Demo{    public static $instance;        private function __Construct()    {        //TODO    }        public static function getInstance()    {        if(!self::$instance){            self::$instance = new static();        }                return self::$instance;    }        public function call()    {        //其他方法    }}

下面有兩種方式執行個體化類:

1.在需要用的地方

$aa = Demo::getInstance();$bb = Demo::getInstance();$cc = Demo::getInstance();

這樣調用肯定是沒問題的,一般情況也是這樣初始化。

2.定義一個普通類,寫個函數初始化,儲存在一個靜態變數,如下:

類:

class Demo{    public function __Construct(){        //TODO    }}

函數:

function get_obj(){    static $obj;    if($obj){        return $obj;    }else{        $obj = new Demo;        return $obj;    }}

在需要調用的地方這樣寫:

$obj = get_obj();$obj->call();$obj2 = get_obj();$obj2->call();$obj3 = get_obj();$obj3 = get_obj();

這樣不是也只執行個體化一次這個類嗎?

完善的單例應該是這樣的

class Foobar {    static private $instance;        // 禁止外部new Foobar    private function __construct() {    }        // 禁止clone $foobar    private function __clone() {    }        static public function getInstance() {        retrun self::$instance            ?: (self::$instance = new self);    }}

如果還要考慮到繼承的話

class Foo {    static private $instances = [];    protected function __construct() {    }    final private function __clone() {    }    final static public function getInstance() {        $class = get_called_class();        if (!isset(self::$instances[$class])) {            self::$instances[$class] = new static;        }        return self::$instances[$class];    }}class Bar extends Foo {}$foo = Foo::getInstance();$bar = Bar::getInstance();

get_obj()那種寫法,也可以達到目的,但無法禁止new和clone,也就無法做到真正的單例

這問題我也有印象,我也答過一次
http://segmentfault.com/q/1010000003894638
看了一下還是題主你,為毛要問兩遍……

然後你的第二種方式並非單例,請不要陷入摳概念的誤區
偶爾也有你這種用法的,少見,並且不好。在一般情況下用一個特定對象就行了,特殊情況下需要新的執行個體的場合會用,但一般也不會這麼寫(早期的PHP會有一些類這麼做)

= = 所以呢?
兩種寫法而已啊。。。
另外,你無論怎麼看,都還是第一種更清晰,更獨立,更好用啊。。。
第一種封裝、抽象的更好,更加符合物件導向啊。
存一個靜態變數或者另外弄個函數什麼的,你不覺得亂嘛。。。

靜態變數可以定義在函數裡或者類屬性,兩種寫法都可以,但前者封裝性會比較好些。

樓主給了我啟發,過程式編程中,在全域函數內用靜態變數儲存資料庫連接實現單例:

 '127.0.0.1',    'db_username'    => 'root',    'db_password'    => '',    'db_name'        => 'mysql');// functions.phpfunction cn_db() {    global $app;    static $mysqli;    if ($mysqli) {        return $mysqli;    } else {        $mysqli = new mysqli($app['db_host'], $app['db_username'], $app['db_password'], $app['db_name']);        return $mysqli;    }}function cn_foo1() {    $mysqli = cn_db();    return $mysqli->query('select user,host from user where user = \'root\'')->fetch_all();}function cn_foo2() {    $mysqli = cn_db();    return $mysqli->query('select user,host from user')->fetch_all();}// controller + viewprint_r(cn_foo1());print_r(cn_foo2());

$instance = new static(); (樓主這行代碼寫錯了),感覺單例模式就是個思想,你第一個例子就是物件導向,第二個例子既有物件導向,又有面向過程。

單例模式是指整個應用中類只有一個對象執行個體的設計模式。

第二種方式是單例嗎?

class Demo {    public function __construct(){        //TODO    }}function get_obj() {    static $obj;    if($obj){        return $obj;    }else{        $obj = new Demo;        return $obj;    }}var_dump(get_obj());var_dump(new Demo);

得出的是2個不同的執行個體

你那樣寫不符合物件導向思想的,而且你的單例模式也不完整,沒有考慮到clone和extends的情況。可以參考下http://www.xtwind.com/design-pattern-singleton.html

單例模式,是一種設計思想實現方式

單例首先是物件導向裡面的概念,
第二種就不是物件導向

get_obj()那種寫法無法保證外部不new Demo對象

單例的要義第一:私人化構造方法,當然PHP還提供了clone魔術方法,也要私人化。這樣做事為了保證外部執行個體化對象的入口只有一個,只能是我們暴露出來的靜態函數getInstance()

單例模式,三私一公,其中的三私:構造方法,複製魔術方法,執行個體化對象。一公:對外提供的方法

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.