抽象工厂模式
模式定义
抽象工厂模式为一组相关或相互依赖的对象创建提供接口,而无需指定其具体实现类。抽象工厂的客户端不关心如何创建这些对象,只关心如何将它们组合到一起。该设计模式实现了设计模式的依赖倒置原则,因为最终由具体子类创建具体组件。
抽象工厂模式的优势
提供一个间接的层(即“抽象工厂”)抽象一组相关或依赖对象的创建而不是直接指定具体实现类。该“工厂”对象的职责是为不同平台提供创建服务。客户端不需要直接创建平台对象,而是让工厂去做这件事。 这种机制让替换平台变得简单,因为抽象工厂的具体实现类只有在实例化的时候才出现,如果要替换的话只需要在实例化的时候指定具体实现类即可。
代码实现
AbstractFactory\AbstractFactory.class.php
<?php
namespace AbstractFactory;
/*
* 抽象工厂类
*
*/
abstract class AbstractFactory
{
abstract public function createText($content);
abstract public function createPicture($path, $name);
}JsonFactory和HtmlFactory是具体工厂,它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
AbstractFactory\JsonFactory.class.php
<?php
namespace AbstractFactory;
use AbstractFactory\Json\Picture;
use AbstractFactory\Json\Text;
/*
* 创建json组件的具体工厂类
*/
class JsonFactory extends AbstractFactory
{
public function createPicture($path, $name)
{
return new Picture($path, $name);
}
public function createText($content)
{
return new Text($content);
}
}AbstractFactory\HtmlFactory.class.php
<?php
namespace AbstractFactory;
use AbstractFactory\Html\Picture;
use AbstractFactory\Html\Text;
/*
* 创建html组件的具体工厂类
*/
class HtmlFactory extends AbstractFactory
{
public function createPicture($path, $name)
{
return new Picture($path, $name);
}
public function createText($content)
{
return new Text($content);
}
}该接口不是抽象工厂设计模式的一部分
AbstractFactory\MediaInterface.class.php
<?php
namespace AbstractFactory;
interface MediaInterface
{
public function render();
}Picture、Text 是抽象产品,它是具体产品继承的父类或者是实现的接口。一般有抽象类或者接口来实现。
AbstractFactory\Picture.class.php
<?php
namespace AbstractFactory;
/*
* 创建图片产品的抽象类
*/
abstract class Picture implements MediaInterface
{
protected $path;
protected $name;
public function __construct($path, $name = '')
{
$this->name = (string) $name;
$this->path = (string) $path;
}
}AbstractFactory\Text.class.php
<?php
namespace AbstractFactory;
/*
* 创建文本产品的抽象类
*/
abstract class Text implements MediaInterface
{
protected $text;
public function __construct($text)
{
$this->text = (string) $text;
}
}Html\Picture、Html\Text、Json\Picture和Json\Text都是具体产品,具体工厂角色所创建的对象就是此角色的实例。由具体的类来实现。
AbstractFactory\Html\Picture.class.php
<?php
namespace AbstractFactory\Html;
use AbstractFactory\Picture as BasePicture;
/*
* html组件创建图片的具体类
*/
class Picture extends BasePicture
{
public function render()
{
return sprintf('<img src="%s" title="%s">', $this->path, $this->name);
}
}AbstractFactory\Html\Text.class.php
<?php
namespace AbstractFactory\Html;
use AbstractFactory\Text as BaseText;
/*
* html组件创建文本的具体类
*/
class Text extends BaseText
{
public function render()
{
return '<div>' . htmlspecialchars($this->text) . '</div>';
}
}AbstractFactory\Json\Picture.class.php
<?php
namespace AbstractFactory\Json;
use AbstractFactory\Picture as BasePicture;
/*
* json组件创建图片的具体类
*/
class Picture extends BasePicture
{
public function render()
{
return json_encode(array('title' => $this->name, 'path' => $this->path));
}
}AbstractFactory\Json\Text.class.php
<?php
namespace AbstractFactory\Json;
use AbstractFactory\Text as BaseText;
/*
* json组件创建文本的具体类
*/
class Text extends BaseText
{
public function render()
{
return json_encode(array('content' => $this->text));
}
}测试方法
AbstractFactory\AbstractFactoryTest.php
<?php
spl_autoload_register(function ($className){
$className = str_replace('\\','/',$className);
include $className.".class.php";
});
use AbstractFactory\HtmlFactory;
use AbstractFactory\JsonFactory;
$htmlFactory = new HtmlFactory();
$htmlTextResult = $htmlFactory->createText('抽象工厂')->render();
$htmlPictureResult = $htmlFactory->createPicture('test.png', '抽象工厂')->render();
$jsonFactory = new JsonFactory();
$jsonTextResult = $jsonFactory->createText("抽象工厂")->render();
$jsonPictureResult = $jsonFactory->createPicture('test.png', '抽象工厂')->render();
echo $htmlTextResult . "\n";
echo $htmlPictureResult . "\n";
echo $jsonTextResult . "\n";
echo $jsonPictureResult . "\n";测试示例
php AbstractFactory/AbstractFactoryTest.php
输出:
<div>抽象工厂</div>
<img src="test.png" title="抽象工厂">
{"content":"\u62bd\u8c61\u5de5\u5382"}
{"title":"\u62bd\u8c61\u5de5\u5382","path":"test.png"}总结
我们以工厂生产产品为例,所谓抽象工厂模式就是我们的抽象工厂约定了可以生产的产品,这些产品都包含多种规格,然后我们可以从抽象工厂为每一种规格派生出具体工厂类,然后让这些具体工厂类生产具体的产品。
以上示例中
AbstractFactory是抽象工厂,这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。它由抽象类或者接口来实现。
JsonFactory和HtmlFactory是具体工厂,它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
Picture、Text 是抽象产品,它是具体产品继承的父类或者是实现的接口。一般有抽象类或者接口来实现。
Html\Picture、Html\Text、Json\Picture和Json\Text都是具体产品,具体工厂角色所创建的对象就是此角色的实例。由具体的类来实现。
客户端需要HTML格式的Text,调用HtmlFactory的createText方法即可,而不必关心其实现逻辑。
代码地址:https://github.com/798256478/design-patterns/tree/master/AbstractFactory