1、定义
抽象工厂是一种创建型设计模式,它能创建一系列相关的对象,而无需指定其具体类。抽象工厂定义了用于创建不同产品的接口,但将实际的创建工作留给了具体工厂类。每个工厂类型都对应一个特定的产品变体。
举个例子:
在本文提到的吉利和比亚迪都是汽车品牌。假设他们都可以自主生产汽车配件,那在组装汽车的时候只要固定在一个厂里调取配件,就不用担心用到其他厂商的配件,保证了整车都是用的一个品牌零部件。其中吉利和比亚迪就相当于两个具体的工厂,工厂可以生产很多的产品,如轮胎、车架、发动机等等。单把轮胎(系列产品中的抽象产品)拎出来看,轮胎就是一个系列,轮胎按照尺寸大小又分为18寸、20寸、22寸(这种具体尺寸的轮胎就是系列产品中的具体产品)等。
2、优缺点
- 优点
- 单一职责原则。可以将产品生成代码抽取到同一位置,使得代码易于维护。
- 开闭原则。向应用程序中引入新产品变体(特征)时,无需修改客户端代码。
- 可以避免客户端和具体产品代码的耦合。
- 可以确保同一工厂生成的产品相互匹配。
- 缺点
- 该模式需要向应用中引入众多接口和类,代码可能会更加复杂。
3、模式结构
-
抽象工厂(AbstractFactory):抽象工厂接口声明了一组能返回不同抽象产品的方法。
-
具体工厂(Concrete Factory):具体工厂可生成属于同一变体的系列产品。完成产品的创建。
-
系列产品中的抽象产品:系列产品中的特定产品必须有一个基础接口。所有产品变体都必须实现这个接口。
-
系列产品中的具体产品:实现了抽象产品所定义的接口。
4、具体代码
抽象工厂(Abstract Factory):抽象工厂接口声明了一组能返回不同抽象产品的方法。
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
interface AbstractFactory
{
/**
* 汽车轮胎
* @return mixed
* @Author: fengzi
* @Date: 2024/3/14 15:20
*/
public function tyre();
/**
* 汽车车架
* @return mixed
* @Author: fengzi
* @Date: 2024/3/14 15:20
*/
public function frame();
}
具体工厂(Concrete Factory):具体工厂可生成属于同一变体的系列产品。完成产品的创建。
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
/**
* 比亚迪工厂
*/
class BydFactory implements AbstractFactory
{
public function tyre(): Tyre
{
return new BydTyre();
}
public function frame(): Frame
{
return new BydFrame();
}
}
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
/**
* 吉利工厂
*/
class GeelyFactory implements AbstractFactory
{
public function tyre(): Tyre
{
return new GeelyTyre();
}
public function frame(): Frame
{
return new GeelyFrame();
}
}
系列产品中的抽象产品接口:系列产品中的特定产品必须有一个基础接口。所有产品变体都必须实现这个接口。
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
/**
* 车架接口
*/
interface Frame
{
/**
* suv的车架
* @return mixed
* @Author: fengzi
* @Date: 2024/3/14 15:29
*/
public function getSuvFrame();
/**
* 轿车的车架
* @return mixed
* @Author: fengzi
* @Date: 2024/3/14 15:29
*/
public function getSedanFrame();
}
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
/**
* 轮胎接口
*/
interface Tyre
{
/**
* 18寸轮胎
* @return mixed
* @Author: fengzi
* @Date: 2024/3/14 15:31
*/
public function get18Tyre();
/**
* 20寸轮胎
* @return mixed
* @Author: fengzi
* @Date: 2024/3/14 15:31
*/
public function get20Tyre();
/**
* 22寸轮胎
* @return mixed
* @Author: fengzi
* @Date: 2024/3/14 15:31
*/
public function get22Tyre();
}
系列产品中的具体产品:实现了抽象产品所定义的接口。
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
/**
* 比亚迪车架
*/
class BydFrame implements Frame
{
public function getSuvFrame()
{
echo "比亚迪SUV车架".PHP_EOL;
}
public function getSedanFrame()
{
echo "比亚迪轿车车架".PHP_EOL;
}
}
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
/**
* 比亚迪造轮胎
*/
class BydTyre implements Tyre
{
public function get18Tyre()
{
echo "比亚迪18寸轮胎".PHP_EOL;
}
public function get20Tyre()
{
echo "比亚迪20寸轮胎".PHP_EOL;
}
public function get22Tyre()
{
echo "比亚迪22寸轮胎".PHP_EOL;
}
}
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
/**
* 吉利车架
*/
class GeelyFrame implements Frame
{
public function getSuvFrame()
{
echo "吉利SUV车架".PHP_EOL;
}
public function getSedanFrame()
{
echo "吉利轿车车架".PHP_EOL;
}
}
<?php
namespace app\admin\service\design_mode\abstract_factory_method;
/**
* 吉利轮胎
*/
class GeelyTyre implements Tyre
{
public function get18Tyre()
{
echo "吉利18寸轮胎".PHP_EOL;
}
public function get20Tyre()
{
echo "吉利20寸轮胎".PHP_EOL;
}
public function get22Tyre()
{
echo "吉利22寸轮胎".PHP_EOL;
}
}
客户端调用代码
<?php
namespace app\admin\controller\design_mode;
use app\admin\service\design_mode\abstract_factory_method\BydFactory;
use app\admin\service\design_mode\abstract_factory_method\GeelyFactory;
/**
* 抽象工厂模式
*/
class AbstractFactoryMethodController
{
/**
* 调用抽象工厂模式
* @return void
* @Author: fengzi
* @Date: 2024/3/14 15:39
*/
public function index()
{
//比亚迪造车
$factory = new BydFactory();
$tyre = $factory->tyre();
$frame = $factory->frame();
$tyre->get18Tyre();
$frame->getSedanFrame();
echo '---------------'.PHP_EOL;
$tyre->get22Tyre();
$frame->getSuvFrame();
echo '==========================='.PHP_EOL;
//吉利造车
$factory = new GeelyFactory();
$tyre = $factory->tyre();
$frame = $factory->frame();
$tyre->get18Tyre();
$frame->getSedanFrame();
echo '---------------'.PHP_EOL;
$tyre->get22Tyre();
$frame->getSuvFrame();
}
}
客户端调用结果展示: