工廠模式 (Factory)
在 Design Pattern 中,工廠模式(Factory) 基本的理念是建構一套完整工廠鍊,可以用來生產各種類別品項。
例如,建構資料庫工廠,可以用來產生 mysql, mongodb, redis…. 等物件。
對於使用者而言,他只需要在初始化工廠時,指定要生產的是什麼,
後續在操作資料庫的行為,都會一致。
例如,我們今天使用的是 mysql,如果改天要換成 pgsql ,只需要更改初始化的設定即可。
針對工廠模式,可以實作的方式很多,分別有以下幾種:
簡單工廠
首先,說明簡單工廠的實作,這裡用 Laravel 的 ORM 作為例子,
在建立資料庫連線時,資料庫的 Factory 會依照設定使用的資料庫類型來建立連線,
實作方式例如:
<?php
class ConnectionFactory
{
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
}
...
/**
* Create a connector instance based on the configuration.
*
* @param array $config
* @return \Illuminate\Database\Connectors\ConnectorInterface
*
* @throws \InvalidArgumentException
*/
public function createConnector(array $config)
{
if (! isset($config['driver'])) {
throw new InvalidArgumentException('A driver must be specified.');
}
if ($this->container->bound($key = "db.connector.{$config['driver']}")) {
return $this->container->make($key);
}
switch ($config['driver']) {
case 'mysql':
return new MySqlConnector;
case 'pgsql':
return new PostgresConnector;
case 'sqlite':
return new SQLiteConnector;
case 'sqlsrv':
return new SqlServerConnector;
}
throw new InvalidArgumentException("Unsupported driver [{$config['driver']}]");
}
/**
* Create a new connection instance.
*
* @param string $driver
* @param \PDO|\Closure $connection
* @param string $database
* @param string $prefix
* @param array $config
* @return \Illuminate\Database\Connection
*
* @throws \InvalidArgumentException
*/
protected function createConnection($driver, $connection, $database, $prefix = '', array $config = [])
{
if ($resolver = Connection::getResolver($driver)) {
return $resolver($connection, $database, $prefix, $config);
}
switch ($driver) {
case 'mysql':
return new MySqlConnection($connection, $database, $prefix, $config);
case 'pgsql':
return new PostgresConnection($connection, $database, $prefix, $config);
case 'sqlite':
return new SQLiteConnection($connection, $database, $prefix, $config);
case 'sqlsrv':
return new SqlServerConnection($connection, $database, $prefix, $config);
}
throw new InvalidArgumentException("Unsupported driver [{$driver}]");
}
}
通常簡單模式,最常被提及的就是會違反 開放封閉原則 Open-Closed Principle(OCP)
工廠抽象化
工廠抽象的方式,可以透過 Abstract 或 Interface 來建構工廠,實作過程僅作描述,不實作邏輯。邏輯會保留到各個類別繼承或implements 之後,強制實作。