日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

php工厂模式和单例模式,php 设计模式之工厂模式、单例模式、注册树模式

發布時間:2023/12/10 php 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php工厂模式和单例模式,php 设计模式之工厂模式、单例模式、注册树模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

php 設計模式之工廠模式、單例模式、注冊樹模式

在軟件工程中,創建型設計模式承擔著對象創建的職責,嘗試創建適合程序上下文的對象,對象創建設計模式的產生是由于軟件工程設計的問題,具體說是向設計中增加復雜度,創建型設計模式解決了程序設計中對象創建的問題。PHP的設計模式有很多種,本文取最簡單的三種模式: 工廠模式、單例模式和注冊樹模式進行簡單的講解。

工廠模式

用工廠方法或者類生成對象,而不是代碼中直接使用 new 關鍵字

比如咱們要做一個連接數據庫的操作,平時都是用mysql。那突然有一天mysql收費了,咋辦?那我們就用Sqlite作來數據庫。如果以傳統的方式創建一個數據庫連接類的話是需要使用關鍵字new MysqlDrive()把這個數據庫實例化,一旦數據庫變更成的話就需要把所有的new MysqlDrive()變更成new SqliteDrive() 這樣替換比較麻煩,并且還容易出錯。所以,下面的工廠模式可以很好的解決這一問題。

廢話不多說,演示一遍就明白了

先看一下目錄結構吧本文演示的全部是遵循PSR-4的編碼規范,當然,是在vendor/目錄下,如果沒有請自己行執行命令composer dumpatuoload 如果您沒有安裝composer那就請看下面文章:

以下是我的目錄結構:

自動忽略DependencyInjection 跟HttpFoundation目錄,這是我計劃下次寫的東西,嘻嘻...

先看看主要文件的代碼吧:

tests/這個目錄是為了讓咱們方便測試的目錄,也就是單元測試目錄

文件: tests/bootstrap.php

include_once __DIR__."/../../../composer/ClassLoader.php";

$loader = new \Composer\Autoload\ClassLoader();

$vendorDir = dirname(dirname(__FILE__));

$baseDir = dirname($vendorDir);

$classMaps = [

'Dudulu\\' => [$vendorDir."/src/"]

];

foreach ($classMaps as $namespace => $path) {

$loader->setPsr4($namespace, $path);

}

$loader->register(true);

咱們需要測試的驅動類MysqlDerive.php

文件: src/DesignPatterns\FactoryMode\DB\MysqlDrive.php

namespace Dudulu\DesignPatterns\FactoryMode;

use Dudulu\DesignPatterns\DB\MysqlDrive;

/**

* Class Factory

* @package Dudulu\DesignPatterns\FactoryMode

*/

class Factory

{

/**

* @return MysqlDrive

*/

public static function database()

{

return new MysqlDrive();

}

}

為了強制讓每種驅動都要有一個連接方式,所以我們需要一個Interface。

文件: src/DesignPatterns/DB/Interfaces/DriveInterface.php

namespace Dudulu\DesignPatterns\DB\Interfaces;

/**

* Interface DriveInterface

* @package Dudulu\DesignPatterns\DB\Interfaces

*/

interface DriveInterface

{

/**

* @return mixed

*/

public function connection();

}

普通模式

先看一個普通demo,直接實例化MysqlDrive對象

include_once "../bootstrap.php";

use Dudulu\DesignPatterns\DB\MysqlDrive;

class FactoryTest extends PHPUnit_Framework_TestCase {

public function testConnection()

{

$db = new MysqlDrive();

$this->assertEquals(true, $db->connection());

}

}

進入src/tests/DesignPattens目錄.

命令行執行: phpunit FactoryTest.php可以發現這樣是好使的...

工廠模式

工廠模式 是一種類,它具有為您創建對象的某些方法。您可以使用工廠類創建對象,而不直接使用 new。這樣,如果您想要更改所創建的對象類型,只需更改該工廠即可。使用該工廠的所有代碼會自動更改。

首先咱們先創建一個Factory.php作為工廠類,然后里邊實現一個靜態方法對相數據庫驅動進行實例化。

文件: src/DesignPatterns/FactoryMode/Factory.php

namespace Dudulu\DesignPatterns\FactoryMode;

use Dudulu\DesignPatterns\DB\MysqlDrive;

/**

* Class Factory

* @package Dudulu\DesignPatterns\FactoryMode

*/

class Factory

{

/**

* @return MysqlDrive

*/

public static function database()

{

return new MysqlDrive();

}

}

創建完后,咱們回到單元測試文件FactoryTest.php

文件: tests/DesignPattens/FactoryTest.php

include_once "../bootstrap.php";

use Dudulu\DesignPatterns\FactoryMode\Factory;

class FactoryTest extends PHPUnit_Framework_TestCase {

public function testConnection()

{

$db = Factory::database();

$this->assertEquals(true, $db->connection());

}

}

再執行一下單元測試命令發現,也能返回成功,這樣的話我們就能很方便的修改任何驅動了。如果我們從mysql換到sqlite了,那么,咱們主要的代碼都不需要更變,只要在Factory.php把connection方法的邊接方式修改完就好了,非常方便。

單例模式

使某個類的對象僅允許創建一個

某些應用程序資源是獨占的,因為有且只有一個此類型的資源。比如,數據庫的連接的獨占。希望在應用程序中共享數據庫連接,因為在保持連接打開或關閉時,它是一種開銷,在獲取單個頁面的過程中更是如此。

比如咱們連接數據庫時,如果不使用單例模式,多個地方都對數據類進行了實例化,那么這樣會造能很多資源浪費,為了解決這問題,對于數據庫類我們只需要實例化一次,后面再次調用它是如果已經實例化,那就直接返回。

來,我們拿一個類來玩一玩...

文件: src/DesignPatterns/SingletonMode/SingletonDB.php

我們創建這個類,然后將構造方法私有化,這樣的話我們就無法使用new關鍵字對這個類進行實例化了。

namespace Dudulu\DesignPatterns\SingletonMode;

use Dudulu\DesignPatterns\DB\Interfaces\DriveInterface;

/**

* Class SingletonDB

* @package Dudulu\DesignPatterns\SingletonMode

*/

class SingletonDB implements DriveInterface

{

/**

* SingletonDB constructor.

*/

private function __construct()

{

}

/**

* @return bool

*/

public function connection()

{

return true;

}

}

那么我們要如何使用這個對象呢?我們需要一個受保護的成員和一個靜態方法:

/**

* @var SingletonDB

*/

protected static $db;

/**

* @return SingletonDB

*/

public static function getInstance()

{

if (self::$db) {

return self::$db;

}

self::$db = new self();

return self::$db;

}

這個方法很好理解,簡單意思就是如果當前屬性已經被設置過了,那就不再進行實例化,而是直接返回,否則實例化當前對象并返回。

與測試上面的方法一樣,測玩玩...

創建測試的文件: tests/DesignPattens/SingletonDBTest.php

include_once "../bootstrap.php";

use Dudulu\DesignPatterns\SingletonMode\SingletonDB;

/**

* Class SingletonDBTest

*/

class SingletonDBTest extends PHPUnit_Framework_TestCase

{

/**

* @return void

*/

public function testConnection()

{

$db = SingletonDB::getInstance();

$this->assertEquals(true, $db->connection());

}

}

執行命令: phpunit SingletonDBTest.php 發現也是可以執行成功的。

如果不信的話,你可以試試多執行幾次SingletonDB::getInstance(); 然后在 getInstance() 方法體里做一個計數器,看看它實例化過幾次。

注冊樹模式

主要用來解決全局共享和交換對象

這個也很好理解,因為我們在框架中經常用到。

注冊樹模式當然也叫注冊模式,注冊器模式。之所以我在這里矯情一下它的名稱,是因為我感覺注冊樹這個名稱更容易讓人理解。注冊樹模式通過將對象實例注冊到一棵全局的對象樹上,需要的時候從對象樹上采摘的模式設計方法。

咱們結合工廠模式及單例模式做一個小例子:

創建文件: src/DesignPatterns/RegisterMode/Register.php

namespace Dudulu\DesignPatterns\RegisterMode;

/**

* Class Register

* @package Dudulu\DesignPatterns\RegisterMode

*/

class Register

{

/**

* @var array

*/

protected static $classMaps = [];

/**

* @param $alias

* @param $class

* @return void

*/

public static function set($alias, $class )

{

self::$classMaps[$alias] = $class;

}

/**

* @param $alias

* @return mixed

*/

public static function get($alias )

{

return self::$classMaps[$alias];

}

}

然后創建一個單例模式的DB類DemoDB.php:

文件: src/DesignPatterns/DB/DemoDB.php

namespace Dudulu\DesignPatterns\DB;

use Dudulu\DesignPatterns\DB\Interfaces\DriveInterface;

class DemoDB implements DriveInterface

{

/**

* @var DemoDB

*/

protected static $db;

/**

* SingletonDB constructor.

*/

private function __construct()

{

}

/**

* @return DemoDB

*/

public static function getInstance()

{

if (self::$db) {

return self::$db;

}

self::$db = new self();

return self::$db;

}

/**

* @return bool

*/

public function connection()

{

return true;

}

}

再工廠模式文件上加入注冊方式代碼:

文件: src/DesignPatterns/FactoryMode/Factory.php

use Dudulu\DesignPatterns\RegisterMode\Register;

/**

* @return DemoDB

*/

public static function testDb()

{

$db = DemoDB::getInstance();

Register::set('DB', $db);

return $db;

}

最后咱們驗證一下:

在tests/目錄下創建RegisterTest.php文件

include_once "../bootstrap.php";

use Dudulu\DesignPatterns\RegisterMode\Register;

use Dudulu\DesignPatterns\DB\DemoDB;

/**

* Class RegisterTest

*/

class RegisterTest extends PHPUnit_Framework_TestCase

{

/**

* @return void

*/

public function testConnection()

{

Register::set('DB', DemoDB::getInstance());

$db = Register::get('DB');

$this->assertEquals(true, $db->connection());

}

}

OK 走一個phpunit RegisterTest.php

返回OK,好棒好棒...☆?(ゝ。?)

__

/ )))    _

`/ イ~   (((ヽ

(  ノ      ̄Y\

| (\ ∧_∧ | )

ヽ ヽ`( `o′ )/ノ/

\ | ⌒Y⌒ / /

|ヽ  |  ノ/

\トー仝ーイ

如果有時間,下次我再寫些關于其他設計模式的文章...

總結

以上是生活随笔為你收集整理的php工厂模式和单例模式,php 设计模式之工厂模式、单例模式、注册树模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。