所以,你給出的例子既不是單身,也沒有工廠。你在這裏只是簡單的「靜態類」 - 只有靜態方法和屬性的類。工廠和單身人士也不能真正解決同樣的問題,因此很難比較和比較它們。
單身
一個Singleton用於管理共享狀態或者避免多次實例化一個類的開銷,當你只有真正需要「的東西之一。」
這裏是一個單身的例子:
class DatabaseConnection {
// Static reference to the single instance of this class we maintain.
protected static $instance;
// Normal instance properties.
protected $mysql;
// Protected constructor to prevent "new DatabaseConnection();"
protected function __construct() {
$this->mysql = new MySQLConnection("localhost", 3306, "appdb");
}
public static function getInstance() {
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function query($sql) {
return $this->mysql->query($sql);
}
}
每當你想在你的代碼中使用了DatabaseConnection()
,你做這樣的:
function getUser($userId) {
$userData = DatabaseConnection::getInstance()->query("SELECT * FROM ...");
}
的DatabaseConnection()
只實例化一次,開始第一次使用它。永遠不會有超過一個創建。
依賴注入/控制
的競爭戰略使用一個Singleton反轉是,基本上,Dependency Injection或Inversion of Control。與依賴注入,而不是具有一個共享的,一類staticly-存儲的實例,該實例僅僅是通過從類類和函數起作用。這裏有一個簡單的例子:
依賴注入的
class DatabaseConnection {
// Normal instance properties.
protected $mysql;
public function __construct() {
$this->mysql = new MySQLConnection("localhost", 3306, "appdb");
}
public function query($sql) {
return $this->mysql->query($sql);
}
}
class UserManager {
protected $databaseConnection;
public function __construct(DatabaseConnection $databaseConnection) {
$this->databaseConnection = $databaseConnection;
}
public function lookupUser($userId) {
return $this->databaseConnection->query("SELECT ...");
}
}
一個好處是,你可以更容易地測試你的代碼。你可以,例如,延長DatabaseConnection
並調用它TestDatabaseConnection
,使之不能實際使用一個真正的MySQL數據庫,它可以使你的測試更快,更可靠。所以,爭論是在單身人士和依賴注入/控制反轉之間,而不是工廠之間。
工廠
所以,現在,Factories:工廠簡化對象的創建,返回不同的類/子類的對象,並有助於從「模板」創建對象。舉個例子,假設我們有不同的類來表示用戶的不同的類型:
class User {
// ...
}
class ModeratorUser extends User {
// ...
}
class AdminUser extends ModeratorUser {
// ...
}
class GuestUser extends User {
// ...
}
這些類包含的方法和屬性,這將是與某種類型的用戶帳戶的工作是有用的。那麼,您將如何通過用戶ID創建並返回其中一個用戶對象,確保返回正確類型的用戶?我們可以用一個工廠模式:
class UserFactory {
public static function fromUserId(DatabaseConnection $db, $userId) {
$record = $db->query("SELECT * FROM users WHERE user_id ...");
// ...
switch ($record['type']) {
case 'admin':
return new AdminUser($userId);
break;
case 'moderator':
return new ModeratorUser($userId);
break;
case 'guest':
return new GuestUser($userId);
break;
default:
case 'normal':
return new User($userId);
break;
}
}
}
然後,加載正確的User
類,你只要致電:
$user = UserFactory::fromUserId($userId);
如果是管理員帳戶,這將是一個AdminUser
;如果它是一個訪客帳戶,它將是一個GuestUser
。
這看起來不像工廠或單件模式。現在,您只需將一些功能分組在某些類中。很難測試你的類實例的狀態。 – mauris
'工廠'創建一些對象。你的代碼在哪裏有對象? –
你可以在這個例子中完全刪除類,並使用簡單的原始全局函數。類在這裏添加的唯一東西是一些命名空間。你沒有任何實際的面向對象的領域,因此這個問題沒有什麼意義。 – deceze