PHP设计模式(四)之细学抽象工厂模式

作者: 温新

分类: 【设计模式】

阅读: 1906

时间: 2019-12-15 15:14:09

一、什么抽象工厂模式
**定义:**抽象工厂提供了一个创建一系列相关或相互依赖的对象接口,无须指定它们具体的类。
**说明:**抽象工厂模式是对工厂方法模式的进一步扩展。
在工厂方法模式中,一个具体工厂只负责生产一类具体的产品,如一个工厂生产手机,那么它只能生产手机。
如果要生产多种形态的产品呢?如手机必须要配备充电器,而工厂方法模式只负责生产手机,其他的一概不管,手机没有充电器,那末无法销售出去。那末如何解决?那就需要抽象工厂模式来生产多种形态的产品了。

举例:去德克士吃饭,最常简的就是套餐了。用户只需要点这个套餐那个套餐就行了。德克士就是A套餐中的抽象工厂,A套餐中有汉堡、鸡翅、饮料。

二、抽象工厂模式结构

为了便于理解此模式,先来了解其概念与结构:

产品等级结构:产品等级结构即产品的继承结构,如一个抽象结构是手机,那么其子类有苹果手机、华为手机、一加手机等手机。因此,抽象手机与具体的品牌手机之间构成了一个产品等级结构。抽象手机是父类,具体子品牌手机是其子类。
产品族:在抽象工厂模式中,产品族是指由同一个工厂生的,位于不同产品等级结构中的一组产品。如华为手机工厂生产的华为手机、华为电脑都是位于手机产品等级结构中。

角色:
抽象工厂(AbstractFactory):担任这个角色的是抽象工厂模式的核心,是与应用系统的商业逻辑无关的。
具体工厂(Factory):这个角色直接在客户端的调用下创建产品的实例,这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统商业逻辑紧密相关的。
抽象产品(AbstractProduct):担任这个角色的类是抽象工厂模式所创建的对象的父类,或它们共同拥有的接口
具体产品(Product):抽象工厂模式所创建的任何产品对象都是一个具体的产品类的实例

三、抽象工厂模式优缺点
优点:
1)分离了具体的类
2)使增加或替换产品族变得容易
3)有利于产品的一致性

缺点
抽象工厂模式难以支持新种类的产品。因为抽象工厂接口确定了可以被创建的产品集合,所以难以扩展抽象工厂以生产新种类的产品。 假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。

四、代码实现

// 素菜接口
AbstractVegetarianDishesInterface.php

<?php
/**
 * 抽象素菜接口
 */

interface AbstractVegetarianDishesInterface
{
    // 生产素菜菜品接口
    public function createVegetarian();
}

// 实现素菜接口
MapotufuProduct.php

<?php
/**
 * 素菜
 * 麻婆豆腐
 */

class MapotufuProduct implements AbstractVegetarianDishesInterface
{
    public function createVegetarian()
    {
        echo '客观,你的麻婆豆腐来了~~';
    }
}

// 实现素菜接口
TomatoProduct.php

<?php
/**
 * 素菜
 * 西红柿炒鸡蛋
 */

class TomatoProduct implements AbstractVegetarianDishesInterface
{
    public function createVegetarian()
    {
        echo '客观,你的西红柿炒鸡蛋来了~~';
    }
}

// 荤菜接口
AbstractMeatDishesInterface.php

<?php
/**
 * 抽象荤菜接口
 */
interface AbstractMeatDishesInterface
{
    // 生产荤菜菜品接口
    public function createMeat();
}

//实现荤菜接口
SteamedFishProduct.php

<?php
/**
 * 荤菜
 * 清蒸鱼
 * 
 */

class SteamedFishProduct implements AbstractMeatDishesInterface
{
    public function createMeat()
    {
        echo '客观,你的清蒸鱼来了~~';
    }
}

// 工厂接口
AbstractRestaurantFactoryInterface.php

<?php
/**
 * 抽象餐厅工厂接口
 */
interface AbstractRestaurantFactoryInterface
{
    // 酒席荤菜工厂接口
    public function meat();

    // 酒席素菜工厂接口
    public function vegetarian();
}

// 具体工厂实现
DishPackageFactoryA.php

<?php
/**
 * DishPackageFactoryA 菜品套餐A
 * 套餐A包含:清蒸鱼、麻婆豆腐
 *
 * 
 * 厨房生产菜品工厂(具体实体工厂)
 */


class DishPackageFactoryA implements AbstractRestaurantFactoryInterface

{

    // 荤菜
    public function meat()
    {
        return new SteamedFishProduct();
    }

    // 素菜
    public function vegetarian()
    {
        return new MapotufuProduct();
    }


}

// 具体工厂实现
DishPackageFactoryB.php

<?php
/**
 * DishPackageFactoryB 菜品套餐B
 * 套餐A包含:西红柿炒鸡蛋、麻婆豆腐
 *
 * 
 * 厨房生产菜品工厂(具体实体工厂)
 */


class DishPackageFactoryB implements AbstractRestaurantFactoryInterface
{

    // 荤菜
    public function meat()
    {
        return new TomatoProduct();
    }

    // 素菜
    public function vegetarian()
    {
        return new MapotufuProduct();
    }

}

// 实现美食
index.php

<?php
/**
 * 客户端上菜
 */
require_once './AbstractMeatDishesInterface.php';
require_once './AbstractRestaurantFactoryInterface.php';
require_once './AbstractVegetarianDishesInterface.php';
require_once './DishPackageFactoryA.php';
require_once './DishPackageFactoryB.php';
require_once './SteamedFishProduct.php';
require_once './MapotufuProduct.php';
require_once './TomatoProduct.php';

// 送上套餐A
$dishPackageA = new DishPackageFactoryA();
echo $dishPackageA->meat()->createMeat();
echo '<br>';
echo $dishPackageA->vegetarian()->createVegetarian();

// 送上套餐B
$dishPackageB = new DishPackageFactoryB();
print_r($dishPackageB->meat()->createVegetarian());
echo '<br>';
echo $dishPackageB->vegetarian()->createVegetarian();

我是夕阳何处寻,期待和优秀的你一起同行!

夕阳何处寻

2019年12月15日

请登录后再评论