Zend Framework中的简单工厂模式 图文
前段时间用来ZF,把他当黑盒感觉不是很好,一直有看其源码的冲动,但是。。。如果一点一点点看的话,挑战确实有些大了。某天又然后想到好久没复习设计模式了。综合一下,复习一个设计模式之后在ZF中找一下使用这模式的源码吧,不读所有源码,读读比较”高级”的部分吧,要说模式,暂时不知道是不是所有模式ZF里面都有,但是应该有足够的模式够我最近看了,在说可以找找其他开源的软件来找模式。这段时间被各种笔试神马乱七八糟的把生活搞得稍微有点乱,但是不管怎样,复习还是必须的吧。再说一下ZF吧,ZF一个好处就是各个component比较独立,component之间没有过多的依赖,这样一来,为使用者提供了方便,当然也为我这样无聊且懒的想看源码的人提供了方便。
今天看看简单工厂,ZF里面不缺模式,更不缺工厂模式,大名鼎鼎的的 Zend_Db就毫不吝啬的使用简单工厂,再ctrl+h(zend studio下)一下会发现factory特别多,如果没猜错应该大多应该也是简单工厂。由于Zend_Db 最常用,我也就自然的会比较想看一下他的实现。在查看源码之前先复习一下怎么用Zend_Db和简单工厂(这里是一个stack,先复习简单工厂)。
复习简单工厂模式
用类图回忆一下,简单工厂类图:
1.复习Zend_Db的使用
如果不知道如何使用,准备看XXX的源码却不知道怎么用XXX,这有点囧,所以先小小的看一下Zend_Db的使用,下面这段是在ZF官方文档里面的(个人不是很喜欢ZF文档,没Yii易读)
/public/index.php
复制代码 代码如下:
$db = Zend_Db::factory('Pdo_Mysql', array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test'
));
这里是把数据库配置也放到代码里面,看起来最简单(实际上其他也不难,只是数据库放置的位置不同,便于管理罢了),但这样在正常情况下不是最好的方式,但是为了突出重点,这里选用这中最简单的方式。注意里面的Zend_Db::factory(‘Pdo_Mysql'…这段
上面生成了一个$db(一个Zend_Db对象),使用上面的$db进行查询如下:
复制代码 代码如下:
$db->setFetchMode(Zend_Db::FETCH_OBJ);
$result = $db->fetchAssoc(
'SELECT bug_id, bug_description, bug_status FROM bugs'
);
继续来自官网文档,这是取记录的模式为Object,再fetch,一切目前看起来都自然而然,但是至今还是把它Zend_Db当作一个黑盒使用。下面可以进入正题。
首先,查看一下zend/Db.php的代码摘要:
复制代码 代码如下:
class Zend_Db
{
/**
设定一些常量和默认值
*/
/**
* Factory for Zend_Db_Adapter_Abstract classes.
*
* First argument may be a string containing the base of the adapter class
* name, e.g. 'Mysqli' corresponds to class Zend_Db_Adapter_Mysqli. This
* name is currently case-insensitive, but is not ideal to rely on this behavior.
* If your class is named 'My_Company_Pdo_Mysql', where 'My_Company' is the namespace
* and 'Pdo_Mysql' is the adapter name, it is best to use the name exactly as it
* is defined in the class. This will ensure proper use of the factory API.
*
* First argument may alternatively be an object of type Zend_Config.
* The adapter class base name is read from the 'adapter' property.
* The adapter config parameters are read from the 'params' property.
*
* Second argument is optional and may be an associative array of key-value
* pairs. This is used as the argument to the adapter constructor.
*
* If the first argument is of type Zend_Config, it is assumed to contain
* all parameters, and the second argument is ignored.
*
* @param mixed $adapter String name of base adapter class, or Zend_Config object.
* @param mixed $config OPTIONAL; an array or Zend_Config object with adapter parameters.
* @return Zend_Db_Adapter_Abstract
* @throws Zend_Db_Exception
*/
public static function factory ($adapter, $config = array())
{
//使用Zend_Config对象,上述方式没有使用,直接使用Array
if ($config instanceof Zend_Config) {
$config = $config->toArray();
}
/*
* Convert Zend_Config argument to plain string
* adapter name and separate config object.
*/
if ($adapter instanceof Zend_Config) {
if (isset($adapter->params)) {
$config = $adapter->params->toArray();
}
if (isset($adapter->adapter)) {
$adapter = (string) $adapter->adapter;
} else {
$adapter = null;
}
}
/*
* Verify that adapter parameters are in an array.
*/
if (! is_array($config)) {
/**
* @see Zend_Db_Exception
*/
require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception(
'Adapter parameters must be in an array or a Zend_Config object');
}
/*
* Verify that an adapter name has been specified.
*/
if (! is_string($adapter) || empty($adapter)) {
/**
* @see Zend_Db_Exception
*/
require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception(
'Adapter name must be specified in a string');
}
/*
* Form full adapter class name
*/
$adapterNamespace = 'Zend_Db_Adapter';
if (isset($config['adapterNamespace'])) {
if ($config['adapterNamespace'] != '') {
$adapterNamespace = $config['adapterNamespace'];
}
unset($config['adapterNamespace']);
}
// Adapter no longer normalized- see http://framework.zend.com/issues/browse/ZF-5606
$adapterName = $adapterNamespace . '_';
$adapterName .= str_replace(' ', '_',
ucwords(str_replace('_', ' ', strtolower($adapter))));
/*
* Load the adapter class. This throws an exception
* if the specified class cannot be loaded.
*/
if (! class_exists($adapterName)) {
require_once 'Zend/Loader.php';
Zend_Loader::loadClass($adapterName);
}
/*
* Create an instance of the adapter class.
* Pass the config to the adapter class constructor.
*/
$dbAdapter = new $adapterName($config);
/*
* Verify that the object created is a descendent of the abstract adapter type.
*/
if (! $dbAdapter instanceof Zend_Db_Adapter_Abstract) {
/**
* @see Zend_Db_Exception
*/
require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception(
"Adapter class '$adapterName' does not extend Zend_Db_Adapter_Abstract");
}
return $dbAdapter;
}
}
最上方的注释非常值得看,它清楚的说明了这个工厂,另外一段比较重要的几段代码(忽略其中的异常处理)是:
复制代码 代码如下:
//factory有一个参数叫做$adapter
public static function factory($adapter, $config = array())
//确定namespace
$adapterNamespace = 'Zend_Db_Adapter';
//用namespace和上面传入的$adapter构造类名
$adapterName = $adapterNamespace . '_';
$adapterName .= str_replace(' ', '_', ucwords(str_replace('_', ' ', strtolower($adapter))));
//用上面生成的类名new出obj,看起来PHP比java方便那么一点点哈(Class.forName(‘XXX').newInstance())
$dbAdapter = new $adapterName($config);
在回想上面使用Zend_Db::factory生成$db的地方:
复制代码 代码如下:
$db = Zend_Db::factory('Pdo_Mysql', array(
'host' => '127.0.0.1',
'username' => 'webuser',
'password' => 'xxxxxxxx',
'dbname' => 'test'
));
factory方法的第一个参数即是$adapter为Pdo_Mysql,记住这里是Pdo_Mysql,再跳跃一下,根据上面的$adapterNamespace = ‘Zend_Db_Adapter';可以看到生成的找到$dbAdapter的值最终必为:Zend_Db_Adapter_Pdo_Mysql,ok,根据此名字找到zend/db/adapter/pdo目录下,哈,这么多熟悉的面孔,看到了熟悉的MySql、Mssql、Sqlite这些老面孔了。
注意,注意,里面还有个低调的Abstract.php,里面他们的父类Zend_Db_Adapter_Pdo_Abstract。打开Mysql.php可以看到
class Zend_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Abstract
嗯,类名Zend_Db_Adapter_Pdo_Mysql和上面生成的名字一样滴,在看看其他几个文件里面的类,他们都继承自Zend_Db_Adapter_Pdo_Abstract,如果要画类图,那就应该会有如下这么一张类图:
接着再加入调用着Client和工厂函数所在的位置Zend_Db,这张简单的类图就应该是,
一个非常非常纯净的简单工厂就这么出来了(不像简单工厂类图吗?那只是因为类的位置没放好)。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

硬碟序號是硬碟的一個重要標識,通常用於唯一標識硬碟以及進行硬體識別。在某些情況下,我們可能需要查詢硬碟序號,例如在安裝作業系統、尋找正確裝置驅動程式或進行硬碟維修等情況下。本文將介紹一些簡單的方法,幫助大家查詢硬碟序號。方法一:使用Windows命令提示字元開啟命令提示字元。在Windows系統中,按下Win+R鍵,輸入"cmd"並按下回車鍵即可開啟命

微信勿擾模式什麼意思如今,隨著智慧型手機的普及和行動網路的快速發展,社群媒體平台已成為人們日常生活中不可或缺的一部分。而微信作為國內最受歡迎的社群媒體平台之一,幾乎每個人都有一個微信帳號。我們可以透過微信與朋友、家人、同事進行即時溝通,分享生活中的點滴,了解彼此的近況。然而,在這個時代,我們也不可避免地面臨資訊過載和隱私洩漏的問題,特別是對於那些需要專注或

長期以來,iOS設備一直能夠使用「健康」應用程式追蹤您的睡眠模式等。但是,當您在睡覺時被通知打擾時,這不是很煩人嗎?這些通知可能無關緊要,因此在此過程中會擾亂您的睡眠模式。雖然免打擾模式是避免睡覺時分心的好方法,但它可能會導致您錯過夜間收到的重要電話和訊息。值得慶幸的是,這就是睡眠模式的用武之地。讓我們了解更多關於它以及如何在iPhone上使用它的資訊。睡眠模式在iPhone上有什麼作用睡眠模式是iOS中專用的專注模式,會根據你在「健康」App中的睡眠定時自動啟動。它可以幫助您設定鬧鐘,然後可以

耳機在現在的生活中非常的常見,是每位用戶都會使用的智慧型設備,有的用戶好奇了r是左還是右耳機怎麼看呢?下面就跟小編來看看耳機r和l分別代表含義介紹吧。 r是左還是右耳機怎麼看答案:右耳。 1.耳機上R是右,right的縮寫,L是左,left的縮寫;2、在耳機上來查找L和R的字母標識,找到透過L和R字母來分辨;3、有的耳機會把R標註為紅色,一般帶有麥克風和按鍵的一側為右;

即使在「請勿打擾」模式下接聽電話也可能是一種非常煩人的體驗。顧名思義,請勿打擾模式可關閉來自郵件、訊息等的所有來電通知和警報。您可以按照這些解決方案集進行修復。修復1–啟用對焦模式在手機上啟用對焦模式。步驟1–從頂部向下滑動以存取控制中心。步驟2–接下來,在手機上啟用「對焦模式」。專注模式可在手機上啟用「請勿打擾」模式。它不會讓您的手機上出現任何來電提醒。修復2–更改對焦模式設定如果對焦模式設定中存在一些問題,則應進行修復。步驟1–打開您的iPhone設定視窗。步驟2–接下來,開啟「對焦」模式設

如何使用Java來寫一個簡單的學生成績報表產生器?學生成績報表產生器是可以幫助老師或教育者快速產生學生成績報告的工具。本文將介紹如何使用Java來撰寫簡單的學生成績報表產生器。首先,我們要定義學生對象和學生成績對象。學生對象包含學生的姓名、學號等基本訊息,而學生成績對象則包含學生的科目成績和平均成績等資訊。以下是一個簡單的學生物件的定義:public

在iPhone15Pro和iPhone15ProMax型號上,Apple推出了一個實體可編程的動作按鈕,取代了音量按鈕上方的傳統響鈴/靜音開關。可以對操作按鈕進行編程以執行幾種不同的功能,但是在靜音和響鈴模式之間切換的能力並沒有消失。預設情況下,長按一次操作按鈕將使裝置靜音,按鈕的觸覺回饋將發出三個脈衝。兩款iPhone15Pro機型在狀態欄中的時間旁邊都會顯示一個劃掉的鈴鐺符號,表示靜音/靜音模式已激活,並且它將一直保持到您再次長按“操作”按鈕取消設備靜音。如果您傾向於將iPhone置於靜音模

如何透過PHP編寫一個簡單的線上預約系統隨著網路的普及和使用者對便利性的追求,線上預約系統越來越受到歡迎。無論是餐廳、醫院、美容院或其他服務業,都可以透過簡單的線上預約系統來提高效率並為使用者提供更好的服務體驗。本文將介紹如何使用PHP編寫一個簡單的線上預約系統,並提供具體的程式碼範例。建立資料庫和表格首先,我們需要建立一個資料庫來儲存預約資訊。在MyS
