什么是简单工厂模式?
以下内容来自 ChatCPT 的回答:
简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,其主要目的是将对象的创建过程封装在一个单独的类中,以便于在需要创建对象时,只需要通过向该类传递参数即可获取所需的对象,而不必直接实例化对象。
简单工厂模式通常包含一个工厂类,该类中包含一个静态方法,该方法接收不同的参数,并根据不同的参数来创建不同的对象。客户端只需要调用工厂类中的方法,并传递所需的参数即可创建相应的对象。
简单工厂模式可以有效地降低客户端与具体产品类之间的耦合度,提高系统的可扩展性和可维护性,同时也可以使客户端代码更加简洁和易于理解。
讲人话?
今天你上工厂干活,你需要跟这三个人配合才能完成任务:张三,李四,王六。
不使用简单工厂设计模式
- 第一件事需要张三跟你拧螺丝,你得自己去喊他,叫他过来跟你拧螺丝。
- 第二件事需要李四跟你搬原料,你得自己去喊他,叫他过来跟你搬原料。
- 第三件事需要王六跟你扫地板,你得自己去喊他,叫他过来跟你扫地板。
使用了简单工厂设计模式
你昨天喊了半天,每干一件事情都要自己亲自去找人,费事不说,有时候还找不到人,还要看人脸色
今天你学聪明了,叫来了厂长,让他帮你叫人
- 第一件事需要张三跟你拧螺丝,你跟厂长说,厂长立马把张三叫过来,跟你一起拧螺丝。
- 第二件事需要李四跟你搬原料,你跟厂长说,厂长立马把李四叫过来,跟你一起搬原料。
- 第三件事需要王六跟你扫地板,你跟厂长说,厂长立马把王六叫过来,跟你一起扫地板。
这里的核心就是,你找到了靠山,厂长,需要什么资源,找他,需要什么人,找他,他就是工厂模式里面的那个工厂。
有什么用?
假设,你领导让你开发一个机票预定系统,机票来源有多家【去哪儿、携程、欣欣旅游】,客户可以根据自己的喜好,选择购买不同公司的机票。
接到这个需求,你二话不说,拿起键盘噼里啪啦狂敲,瞬间对接好了各家供应商的购票下单逻辑。
<?php
interface Flight
{
/**
* 买票了
*/
public function buyTicket();
}
/**
* 去哪儿网
*/
class QunarFlight implements Flight
{
public function buyTicket()
{
echo '欢迎来到【去哪儿网】购买机票' . PHP_EOL;
// 这里省略 210 行代码...
}
}
/**
* 携程
*/
class CtripFlight implements Flight
{
public function buyTicket()
{
echo '欢迎来到【携程】购买机票' . PHP_EOL;
// 这里省略 180 行代码...
}
}
/**
* 欣欣旅游
*/
class CncnFlight implements Flight
{
public function buyTicket()
{
echo '欢迎来到【欣欣旅游】购买机票,这里购买机票折扣很大。' . PHP_EOL;
// 这里省略 21 行代码...
}
}
系统刷的一下子上线了,顾客来了,开始订票了。
老板乐开了花。
// 顾客A要了一张去哪儿的机票
$customerA = new QunarFlight();
$customerA->buyTicket();
// 顾客B要了一张携程的机票
$customerB = new CtripFlight();
$customerB->buyTicket();
// 顾客C要了一张欣欣旅游的机票
$customerC = new CncnFlight();
$customerD->buyTicket();
干的很不错,你们公司业务蒸蒸日上,又陆续对接了50家机票供应商。顾客需要什么我就给你 new 什么。:)
$customer1 = new Supplier1Flight();
$customer2 = new Supplier2Flight();
$customer3 = new Supplier3Flight();
$customer4 = new Supplier4Flight();
$customer5 = new Supplier5Flight();
$customer6 = new Supplier6Flight();
$customer7 = new Supplier7Flight();
$customer8 = new Supplier8Flight();
$customer9 = new Supplier9Flight();
...
今天你们公司新入职了个程序媛,她看到这段代码后,呆住了,震惊了,满脸惊讶坐在那里盯着屏幕一动不动,陷入沉思。
你问她:怎么样,代码写得太棒了惊艳到你了是吗?公司的业务全靠它起来的。
妹子回过神来,说:你有没有听说过简单工厂模式?
你瞬间炸了?啥?工厂模式?还是简单的??那玩意有啥用?别整那些有的没的,好好看代码,等下安排任务给你了。
要强的你,下班后,偷偷网上google了一下,看了180篇相关的文章,默默留下无知的眼泪,拿起键盘又一阵狂敲。
/**
* 我是机票工厂,你要哪家供应商的机票,跟我说名字就行,我拿给你
*/
class FlightFactory
{
public static function getFlightSupplier(string $supplierName)
{
switch ($supplierName) {
case 'qunar':
return new QunarFlight();
case 'ctrip':
return new CtripFlight();
case 'cncn':
return new CncnFlight();
default:
throw new \http\Exception\InvalidArgumentException('你选择供应商我们暂时还没接入,请你先选择其他供应商下单,我们将尽快接入');
}
}
}
// 顾客A要欣欣旅游的机票
$customerA = FlightFactory::getFlightSupplier('cncn');
// 顾客B要携程的票
$customerB = FlightFactory::getFlightSupplier('qunar');
// 顾客C要去哪儿的票
$customerC = FlightFactory::getFlightSupplier('ctrip');
// 顾客D要途牛的票
$customerD = FlightFactory::getFlightSupplier('tuniu');
Laravel源码中,有没有用到该设计模式的地方?
这里使用的是 Laravel 8.83.27
具体使用:根据配置信息返回不同的数据库连接对象
<?php
namespace Illuminate\Database\Connectors;
use Illuminate\Contracts\Container\Container;
use Illuminate\Database\Connection;
use Illuminate\Database\MySqlConnection;
use Illuminate\Database\PostgresConnection;
use Illuminate\Database\SQLiteConnection;
use Illuminate\Database\SqlServerConnection;
use Illuminate\Support\Arr;
use InvalidArgumentException;
use PDOException;
class ConnectionFactory
{
/**
* 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}].");
}
}