PHP设计模式(三)之工厂方法模式
一、什么是工厂方法模式
1)工厂方法模式(Factory Method Pattern),又称 多态性工厂模式(Polymorphic Factory)
2)工厂方法模式就是为每一个产品提供独立的工厂类,根据不同的工厂实例来生产不同的产品。
二、工厂方法模式结构
Product抽象产品定义子类要实现的产品接口方法
ConcreteProduct 具体产品实现抽象产品中定义的产品,且工厂方法模式创建的每一个产品都是具体产品的实例
Factory 抽象工厂工厂方法模式的核心所在,其定义了具体工厂所要实现的具体产品接口(这一步是核心)
ConcreteFactory 具体工厂
案例归纳
// 产品接口
interface product
{
public function getProduct();
}
// 具体产品
class specificProduct implements product
{
public function getProduct()
{
echo 'product';
}
}
// 工厂接口
interface factory
{
public function product();
}
// 具体工厂
class specificFactory implements factory
{
public function getFactory()
{
return new specificProduct();
}
}
三、工厂方法模式的优缺点
优点
1)具有良好的封装性。调用产品只需要从工厂中获取即可。
2)易扩展。曾加产品时,只需要添加添加产品类(扩展),不用修改核心代码。
3)屏蔽产品类,解除耦合。
缺点
每新增一个产品时就要新增一个具体产品类与具体工厂类,增加了系统的复杂度
四、简单工厂模式与工厂方法模式对比
简单工厂方法模式
新增产品类时,需要修改核心工厂类,不仅破坏了开闭原则而且当产品达到一定的数量时,难以维护。
工厂方法模式
把创建产品的工作交给子类工厂来做,当新增产品时,只需要新增产品类即可,解决了简单工厂方法模式修改核心代码的缺点,且易于扩展。
五、举例说明
从上一篇的简单工厂模式说明,目前餐厅有两个菜品,分别是酸辣土豆丝、鱼香茄子。为了吸引顾客,餐馆不断创新,推出新的菜品,如新增麻婆豆腐、番茄炒鸡蛋...众多菜品,这就使得餐厅工厂核心类不断扩大,达到一定量级时难以维护,且修改核心部件容易出错,为了解决这个问题,餐馆老板想到一个解决办法,把核心独立出来,新增餐品时,我只要在核心工厂中定义新的菜名,其他的则由子类工厂来实现,这样不是更好吗?这就是工厂方法模式。
解释:
1)上面独立出来的工厂接口可以看作是一个实体工厂,它只需要定义哪些是必须要实现的菜品,它的任务就是把要做的告诉工厂车间
2)具体工厂类可以看作是实体工厂的每一个车间,它来实际生产产品。
六、代码实现
// Ps:这个接口是工厂方法模式的核心 RestaurantMethodFactoryInterface.php
<?php
/**
* 核心工厂接口
*/
interface RestaurantMethodFactoryInterface
{
// 生产产品接口
public function makeCookDish();
}
CookInterface.php
<?php
/**
* 烹饪核心菜品接口,规定做菜的步骤
*/
interface Cook
{
// 准备食材
public function prepareIngredients();
// 烹饪食材
public function cooking();
// 上菜
public function serving();
}
BlackBean.php
<?php
/**
* 酸辣土豆丝菜品
*/
class BlackBean implements Cook
{
// 准备食材
public function prepareIngredients()
{
echo '步骤一:准备食材:土豆、花椒、白醋、盐、干辣椒、葱蒜...';
}
// 烹饪食材
public function cooking()
{
echo '步骤二:烹饪食材:土豆切丝去除淀粉,锅中水开,土豆入水10s捞出...';
}
// 上菜
public function serving()
{
echo '步骤三:上菜:你的酸辣土豆丝来了~~';
}
}
Eggplant.php
<?php
/**
* 鱼香茄子类菜品
*/
class Eggplant implements Cook
{
// 准备食材
public function prepareIngredients()
{
echo '步骤一:准备食材:茄子、葱姜蒜、豆瓣酱、水淀粉...';
}
// 烹饪食材
public function cooking()
{
echo '步骤二:烹饪食材:锅内放油,放入肉糜煸炒,然后下葱姜蒜、豆瓣酱一起炒香....把茄子也一起放下去煮';
}
// 上菜
public function serving()
{
echo '步骤三:上菜:你的鱼香茄子来了~~';
}
}
BlackBeanFactory.php
<?php
/**
* 酸辣土豆丝工厂
*/
class BlackBeanFactory implements RestaurantMethodFactoryInterface
{
// 生产酸辣土豆丝
public function makeCookDish()
{
return new BlackBean();
}
}
EggplantFactroy.php
<?php
/**
* 鱼香茄子工厂
*/
class EggplantFactroy implements RestaurantMethodFactoryInterface
{
// 生产鱼香茄子
public function makeCookDish()
{
return new Eggplant();
}
}
// 这是新增的麻婆豆腐 MapoTuFu.php
<?php
/**
* 麻婆豆腐菜品
*/
class MapoTuFu implements Cook
{
// 准备食材
public function prepareIngredients()
{
echo '步骤一:准备食材:豆腐、豆瓣、水淀粉...';
}
// 烹饪食材
public function cooking()
{
echo '步骤二:烹饪食材:锅中热油,放入豆瓣炒香...';
}
// 上菜
public function serving()
{
echo '步骤三:上菜:你的麻辣豆腐来了~~';
}
}
MapoTuFuFactory.php
<?php
/**
* 麻婆豆腐工厂
*/
class MapoTuFuFactory implements RestaurantMethodFactoryInterface
{
// 生产麻婆豆腐
public function makeCookDish()
{
// 开始生产菜品(实例化菜品类)
return new MapoTuFu();
}
}
index.php
<?php
/**
* 餐厅
*/
require_once './CookInterface.php';
require_once './RestaurantMethodFactoryInterface.php';
require_once './EggplantFactroy.php';
require_once './Eggplant.php';
// 鱼香茄子
require_once './MapoTuFuFactory.php';
require_once './MapoTuFu.php';
// 生产鱼香茄子
$maPoTuFuFactory = new MapoTuFuFactory();
$maPoTuFuProduct = $maPoTuFuFactory->makeCookDish();
// 准备食材
$maPoTuFu = $maPoTuFuProduct->prepareIngredients();
// 烹饪食材
$maPoTuFu = $maPoTuFuProduct->cooking();
// 你的鱼香茄子来了
$maPoTuFu = $maPoTuFuProduct->serving();
print_r($maPoTuFu);
至此,工厂方法模式完毕,^_^ 对比简单工厂模式与工厂方法模式,优缺点一目了然。
我是夕阳何处寻,期待和优秀的你一起同行!
夕阳何处寻
2019年12月11日