抽象工厂模式
模式定义
抽象工厂模式为一组相关或相互依赖的对象创建提供接口,而无需指定其具体实现类。抽象工厂的客户端不关心如何创建这些对象,只关心如何将它们组合到一起。该设计模式实现了设计模式的依赖倒置原则,因为最终由具体子类创建具体组件。
抽象工厂模式的优势
提供一个间接的层(即“抽象工厂”)抽象一组相关或依赖对象的创建而不是直接指定具体实现类。该“工厂”对象的职责是为不同平台提供创建服务。客户端不需要直接创建平台对象,而是让工厂去做这件事。 这种机制让替换平台变得简单,因为抽象工厂的具体实现类只有在实例化的时候才出现,如果要替换的话只需要在实例化的时候指定具体实现类即可。
代码实现
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