利用靜態方法定義一個簡單工廠,這是很常見的技巧,常被稱為靜態工廠(Static Factory)。靜態工廠是 new 關鍵詞實例化的另一種替代,也更像是一種編程習慣而非一種設計模式。和簡單工廠相比,靜態工廠通過一個靜態方法去實例化對象。為何使用靜態方法?因為不需要創建工廠實例就可以直接獲取對象。 ...
應用舉例
yii\db\ActiveRecord
//獲取 Connection 實例
public static function getDb()
{
return Yii::$app->getDb();
}
//獲取 ActiveQuery 實例
public static function find()
{
return Yii::createObject(ActiveQuery::className(), [get_called_class()]);
}
這裡用到了靜態工廠模式。
靜態工廠
利用靜態方法定義一個簡單工廠,這是很常見的技巧,常被稱為靜態工廠(Static Factory)。靜態工廠是 new 關鍵詞實例化的另一種替代,也更像是一種編程習慣而非一種設計模式。和簡單工廠相比,靜態工廠通過一個靜態方法去實例化對象。為何使用靜態方法?因為不需要創建工廠實例就可以直接獲取對象。
和Java不同,PHP的靜態方法可以被子類繼承。當子類靜態方法不存在,直接調用父類的靜態方法。不管是靜態方法還是靜態成員變數,都是針對的類而不是對象。因此,靜態方法是共用的,靜態成員變數是共用的。
代碼實現
//靜態工廠
class StaticFactory
{
//靜態方法
public static function factory(string $type): FormatterInterface
{
if ($type == 'number') {
return new FormatNumber();
}
if ($type == 'string') {
return new FormatString();
}
throw new \InvalidArgumentException('Unknown format given');
}
}
//FormatString類
class FormatString implements FormatterInterface
{
}
//FormatNumber類
class FormatNumber implements FormatterInterface
{
}
interface FormatterInterface
{
}
使用:
//獲取FormatNumber對象
StaticFactory::factory('number');
//獲取FormatString對象
StaticFactory::factory('string');
//獲取不存在的對象
StaticFactory::factory('object');
Yii2中的靜態工廠
Yii2 使用靜態工廠的地方非常非常多,比簡單工廠還要多。關於靜態工廠的使用,我們可以再舉一例。
我們可通過重載靜態方法 ActiveRecord::find() 實現對where查詢條件的封裝:
//預設篩選已經審核通過的記錄
public function checked($status = 1)
{
return $this->where(['check_status' => $status]);
}
和where的鏈式操作:
Student::find()->checked()->where(...)->all();
Student::checked(2)->where(...)->all();
詳情請參考我的另一篇文章 Yii2 Scope 功能的改進