php 抽象工厂类实例,抽象工厂模式(Abstract Factory)

抽象工厂模式(Abstract Factory)

由 学院君 创建于5年前, 最后更新于 1个月前

版本号 #3

34456 views

31 likes

1 collects

1、模式概述

抽象工厂模式为一组相关或相互依赖的对象创建提供接口,而无需指定其具体实现类。抽象工厂的客户端不关心如何创建这些对象,只关心如何将它们组合到一起。

2、问题引出

举个例子,如果某个应用是可移植的,那么它需要封装平台依赖,这些平台可能包括窗口系统、操作系统、数据库等等。这种封装如果未经设计,通常代码会包含多个 if 条件语句以及对应平台的操作。这种硬编码不仅可读性差,而且扩展性也不好。

3、解决方案

提供一个间接的层(即“抽象工厂”)抽象一组相关或依赖对象的创建而不是直接指定具体实现类。该“工厂”对象的职责是为不同平台提供创建服务。客户端不需要直接创建平台对象,而是让工厂去做这件事。

这种机制让替换平台变得简单,因为抽象工厂的具体实现类只有在实例化的时候才出现,如果要替换的话只需要在实例化的时候指定具体实现类即可。

4、UML类图

抽象工厂为每个产品(具体实现)定义了工厂方法,每个工厂方法封装了new操作符和具体类(指定平台的产品类),每个“平台”都是抽象工厂的派生类。

a67791631119992308308064b6e38d24.png

5、代码实现

AbstractFactory.php

namespace DesignPatterns\Creational\AbstractFactory;

/**

* 抽象工厂类

*

* 该设计模式实现了设计模式的依赖倒置原则,因为最终由具体子类创建具体组件

*

* 在本例中,抽象工厂为创建 Web 组件(产品)提供了接口,这里有两个组件:文本和图片,有两种渲染方式:HTML

* 和 JSON,对应四个具体实现类。

*

* 尽管有四个具体类,但是客户端只需要知道这个接口可以用于构建正确的 HTTP 响应即可,无需关心其具体实现。

*/

abstract class AbstractFactory

{

/**

* 创建本文组件

*

* @param string $content

*

* @return Text

*/

abstract public function createText($content);

/**

* 创建图片组件

*

* @param string $path

* @param string $name

*

* @return Picture

*/

abstract public function createPicture($path, $name = '');

}

JsonFactory.php

namespace DesignPatterns\Creational\AbstractFactory;

/**

* JsonFactory类

*

* JsonFactory 是用于创建 JSON 组件的工厂

*/

class JsonFactory extends AbstractFactory

{

/**

* 创建图片组件

*

* @param string $path

* @param string $name

*

* @return Json\Picture|Picture

*/

public function createPicture($path, $name = '')

{

return new Json\Picture($path, $name);

}

/**

* 创建文本组件

*

* @param string $content

*

* @return Json\Text|Text

*/

public function createText($content)

{

return new Json\Text($content);

}

}

HtmlFactory.php

namespace DesignPatterns\Creational\AbstractFactory;

/**

* HtmlFactory类

*

* HtmlFactory 是用于创建 HTML 组件的工厂

*/

class HtmlFactory extends AbstractFactory

{

/**

* 创建图片组件

*

* @param string $path

* @param string $name

*

* @return Html\Picture|Picture

*/

public function createPicture($path, $name = '')

{

return new Html\Picture($path, $name);

}

/**

* 创建文本组件

*

* @param string $content

*

* @return Html\Text|Text

*/

public function createText($content)

{

return new Html\Text($content);

}

}

MediaInterface.php

namespace DesignPatterns\Creational\AbstractFactory;

/**

* MediaInterface接口

*

* 该接口不是抽象工厂设计模式的一部分, 一般情况下, 每个组件都是不相干的

*/

interface MediaInterface

{

/**

* JSON 或 HTML(取决于具体类)输出的未经处理的渲染

*

* @return string

*/

public function render();

}

Picture.php

namespace DesignPatterns\Creational\AbstractFactory;

/**

* Picture类

*/

abstract class Picture implements MediaInterface

{

/**

* @var string

*/

protected $path;

/**

* @var string

*/

protected $name;

/**

* @param string $path

* @param string $name

*/

public function __construct($path, $name = '')

{

$this->name = (string) $name;

$this->path = (string) $path;

}

}

Text.php

namespace DesignPatterns\Creational\AbstractFactory;

/**

* Text类

*/

abstract class Text implements MediaInterface

{

/**

* @var string

*/

protected $text;

/**

* @param string $text

*/

public function __construct($text)

{

$this->text = (string) $text;

}

}

Json/Picture.php

namespace DesignPatterns\Creational\AbstractFactory\Json;

use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;

/**

* Picture类

*

* 该类是以 JSON 格式输出的具体图片组件类

*/

class Picture extends BasePicture

{

/**

* JSON 格式输出

*

* @return string

*/

public function render()

{

return json_encode(array('title' => $this->name, 'path' => $this->path));

}

}

Json/Text.php

namespace DesignPatterns\Creational\AbstractFactory\Json;

use DesignPatterns\Creational\AbstractFactory\Text as BaseText;

/**

* Class Text

*

* 该类是以 JSON 格式输出的具体文本组件类

*/

class Text extends BaseText

{

/**

* 以 JSON 格式输出的渲染

*

* @return string

*/

public function render()

{

return json_encode(array('content' => $this->text));

}

}

Html/Picture.php

namespace DesignPatterns\Creational\AbstractFactory\Html;

use DesignPatterns\Creational\AbstractFactory\Picture as BasePicture;

/**

* Picture 类

*

* 该类是以 HTML 格式渲染的具体图片类

*/

class Picture extends BasePicture

{

/**

* HTML 格式输出的图片

*

* @return string

*/

public function render()

{

return sprintf('%s', $this->path, $this->name);

}

}

Html/Text.php

namespace DesignPatterns\Creational\AbstractFactory\Html;

use DesignPatterns\Creational\AbstractFactory\Text as BaseText;

/**

* Text 类

*

* 该类是以 HTML 渲染的具体文本组件类

*/

class Text extends BaseText

{

/**

* HTML 格式输出的文本

*

* @return string

*/

public function render()

{

return '

' . htmlspecialchars($this->text) . '
';

}

}

6、测试代码

Tests/AbstractFactoryTest.php

namespace DesignPatterns\Creational\AbstractFactory\Tests;

use DesignPatterns\Creational\AbstractFactory\AbstractFactory;

use DesignPatterns\Creational\AbstractFactory\HtmlFactory;

use DesignPatterns\Creational\AbstractFactory\JsonFactory;

/**

* AbstractFactoryTest 用于测试具体的工厂

*/

class AbstractFactoryTest extends \PHPUnit_Framework_TestCase

{

public function getFactories()

{

return array(

array(new JsonFactory()),

array(new HtmlFactory())

);

}

/**

* 这里是工厂的客户端,我们无需关心传递过来的是什么工厂类,

* 只需以我们想要的方式渲染任意想要的组件即可。

*

* @dataProvider getFactories

*/

public function testComponentCreation(AbstractFactory $factory)

{

$article = array(

$factory->createText('Laravel学院'),

$factory->createPicture('/image.jpg', 'laravel-academy'),

$factory->createText('LaravelAcademy.org')

);

$this->assertContainsOnly('DesignPatterns\Creational\AbstractFactory\MediaInterface', $article);

}

}

执行测试:

phpunit /path/to/AbstractFactoryTest.php

7、总结

最后我们以工厂生产产品为例,所谓抽象工厂模式就是我们的抽象工厂约定了可以生产的产品,这些产品都包含多种规格,然后我们可以从抽象工厂为每一种规格派生出具体工厂类,然后让这些具体工厂类生产具体的产品。以上示例中AbstractFactory是抽象工厂,JsonFactory和HtmlFactory是具体工厂,Html\Picture、Html\Text、Json\Picture和Json\Text都是具体产品,客户端需要HTML格式的Text,调用HtmlFactory的createText方法即可,而不必关心其实现逻辑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值