PHP设计模式之工厂模式(Factory Pattern)的讲解


Posted in PHP onMarch 21, 2019

面向对象编程中,工厂模式是我们最常用的实例化对象模式,工厂类就是一个专门用来创建其它对象的类,工厂类在多态性编程实践中是非常重要的。它允许动态替换类,修改配置,会使应用程序更加灵活。掌握工厂模式对Web开发是必不可少的,它会给你的系统带来更大的可扩展性和尽量少的修改量。

工厂模式通常用来返回类似接口的不同的类,工厂的一种常见用法就是创建多态的提供者。

通常工厂模式有一个关键的构造,即一般被命名为factory的静态方法。这个静态方法可以接受任意数量的参数,并且必须返回一个对象。

一个非常贴近生活的例子来告诉你什么是工厂模式

但是工厂模式真的是个累赘吗?其实并不是!他能够作为一种设计模式流传至今,一定是有他的道理的!只不过我们看到的例子只能说明工厂模式是什么,并不能很好说明工厂模式的优点,所以我们学会后并不知道为什么要使用工厂模式,以及什么时候应该去使用工厂模式!

其实工厂模式在我们的现实生活中非常常见,下面我举个生活中的例子,大家应该就能明白工厂模式的用处在哪里了!

麦当劳大家都吃过吧?我们去点餐的时候,我们可以点一个汉堡,一杯可乐,一个薯条。我们还可以点一杯可乐,一个薯条。点完之后点餐员会问我们一句还要别的吗?你说不要了! 然后你的这一份餐就点完了,可以给钱了。咦,我们发现这是一个建造者模式(Builder Pattern)啊!

(ps:这确实是突然发现的,之前写建造者模式那篇文章的时候并没有想到这个例子)

基本的工厂类:

<?php
 class Fruit {
 // 对象从工厂类返回
 }
 Class FruitFactory {
 public static function factory() {
  // 返回对象的一个新实例
  return new Fruit();
 }
 }
 // 调用工厂
 $instance = FruitFactory::factory();
?>

利用工厂类生产对象:

<?php
class Example
{
  // The parameterized factory method
  public static function factory($type)
  {
    if (include_once 'Drivers/' . $type . '.php') {
      $classname = 'Driver_' . $type;
      return new $classname;
    } else {
      throw new Exception('Driver not found');
    }
  }
}
// Load a MySQL Driver
$mysql = Example::factory('MySQL');
// Load an SQLite Driver
$sqlite = Example::factory('SQLite');
?>

一个完整的工厂类:

下面的程序定义了一个通用的工厂类,它生产能够保存你所有操作的空对象,你可以获得一个实例,这些操作都在那个实例中了。

<?php
  /**
   * Generic Factory class
   * This Factory will remember all operations you perform on it,
   * and apply them to the object it instantiates.
   */
  class FruitFactory {
    private $history, $class, $constructor_args;
    /**
     * Create a factory of given class. Accepts extra arguments to be passed to
     * class constructor.
     */
    function __construct( $class ) {
      $args = func_get_args();
      $this->class = $class;
      $this->constructor_args = array_slice( $args, 1 );
    }
    function __call( $method, $args ) {
      $this->history[] = array(
        'action'  => 'call',
        'method'  => $method,
        'args'  => $args
      );
    }
    function __set( $property, $value ) {
      $this->history[] = array(
        'action'  => 'set',
        'property'  => $property,
        'value'    => $value
      );
    }
    /**
     * Creates an instance and performs all operations that were done on this MagicFactory
     */
    function instance() {
      # use Reflection to create a new instance, using the $args 
      $reflection_object = new ReflectionClass( $this->class ); 
      $object = $reflection_object->newInstanceArgs( $this->constructor_args ); 
      # Alternative method that doesn't use ReflectionClass, but doesn't support variable
      # number of constructor parameters.
      //$object = new $this->class();
      # Repeat all remembered operations, apply to new object.
      foreach( $this->history as $item ) {
        if( $item['action'] == 'call' ) {
          call_user_func_array( array( $object, $item['method'] ), $item['args'] );
        }
        if( $item['action'] == 'set' ) {
          $object->{$item['property']} = $item['value'];
        }
      }
      # Done
      return $object;
    }
  }
  class Fruit {
    private $name, $color;
    public $price;
    function __construct( $name, $color ) {
      $this->name = $name;
      $this->color = $color;
    }
    function setName( $name ) {
      $this->name = $name;
    }
    function introduce() {
      print "Hello, this is an {$this->name} {$this->sirname}, its price is {$this->price} RMB.";
    }
  }
  # Setup a factory
  $fruit_factory = new FruitFactory('Fruit', 'Apple', 'Gonn');
  $fruit_factory->setName('Apple');
  $fruit_factory->price = 2;
  # Get an instance
  $apple = $fruit_factory->instance();
  $apple->introduce();
?>

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

工厂模式可以分为三类:

  • 简单工厂模式(Simple Factory)
  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)

这三种模式从上到下逐步抽象,并且更具一般性。

简单工厂模式又称静态工厂方法模式;从命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。

工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。

工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口。那我们是否一定要在代码中遍布工厂呢?大可不必。也许在下面情况下你可以考虑使用工厂方法模式:

  • 当客户程序不需要知道要使用对象的创建过程。
  • 客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。如果你想了解更多相关内容请查看下面相关链接

PHP 相关文章推荐
php 中include()与require()的对比
Oct 09 PHP
色色整理的PHP面试题集锦
Mar 08 PHP
php变量作用域的深入解析
Jun 03 PHP
详细解读PHP中接口的应用
Aug 12 PHP
WordPress中注册菜单与调用菜单的方法详解
Dec 18 PHP
php制作圆形用户头像的实例_自定义封装类源代码
Sep 18 PHP
PHP常见数组排序方法小结
Aug 20 PHP
PHP递归的三种常用方式
Feb 28 PHP
php实现登录页面的简单实例
Sep 29 PHP
PHP设计模式入门之迭代器模式原理与实现方法分析
Apr 26 PHP
PHP函数用法详解【初始化、嵌套、内置函数等】
Jun 02 PHP
thinkphp5 路由分发原理
Mar 18 PHP
使用PHP反射机制来构造&quot;CREATE TABLE&quot;的sql语句
Mar 21 #PHP
启用OPCache提高PHP程序性能的方法
Mar 21 #PHP
Discuz不使用插件实现简单的打赏功能
Mar 21 #PHP
PHP+RabbitMQ实现消息队列的完整代码
Mar 20 #PHP
PHP实现的数据对象映射模式详解
Mar 20 #PHP
PHP单例模式数据库连接类与页面静态化实现方法
Mar 20 #PHP
PHP实现的策略模式示例
Mar 20 #PHP
You might like
PHILIPS AE3805收音机的分析打磨
2021/03/02 无线电
如何用php生成扭曲及旋转的验证码图片
2013/06/07 PHP
PHP的变量类型和作用域详解
2014/03/12 PHP
ThinkPHP模板比较标签用法详解
2014/06/30 PHP
php中__destruct与register_shutdown_function执行的先后顺序问题
2014/10/17 PHP
php中字符串和正则表达式详解
2014/10/23 PHP
yii2缓存Caching基本用法示例
2016/07/18 PHP
读jQuery之二(两种扩展)
2011/06/11 Javascript
jQuery EasyUI API 中文文档 - DataGrid数据表格
2011/11/17 Javascript
解决jquery异步按一定的时间间隔刷新问题
2012/12/10 Javascript
JS字符串截取函数实例
2013/12/27 Javascript
JavaScript中一个奇葩的IE浏览器判断方法
2014/04/16 Javascript
AngularJs 动态加载模块和依赖
2016/09/15 Javascript
jQuery实现的网页换肤效果示例
2016/09/20 Javascript
Vue.js实现价格计算器功能
2020/03/30 Javascript
layui的table单击行勾选checkbox功能方法
2018/08/14 Javascript
Vue.set()动态的新增与修改数据,触发视图更新的方法
2018/09/15 Javascript
vue实现PC端录音功能的实例代码
2019/06/05 Javascript
ES6基础之字符串和函数的拓展详解
2019/08/22 Javascript
layui实现checkbox的目录树tree的例子
2019/09/12 Javascript
[02:59]2014DOTA2西雅图国际邀请赛 圆满落幕中国夺冠
2014/07/23 DOTA
[01:04:35]2018DOTA2亚洲邀请赛 4.3 突围赛 Secret vs VG 第一场
2018/04/04 DOTA
Python使用pygame模块编写俄罗斯方块游戏的代码实例
2015/12/08 Python
解决python打不开文件(文件不存在)的问题
2019/02/18 Python
python 实现字符串下标的输出功能
2020/02/13 Python
Tensorflow中k.gradients()和tf.stop_gradient()用法说明
2020/06/10 Python
教师考核评语
2014/04/28 职场文书
关爱残疾人演讲稿
2014/05/24 职场文书
离婚撤诉申请书范本
2015/05/18 职场文书
单位工作证明范本
2015/06/15 职场文书
婚庆开业庆典主持词
2015/06/30 职场文书
2016幼儿教师自荐信范文
2016/01/28 职场文书
加薪申请书应该这样写!
2019/07/04 职场文书
写好Python代码的几条重要技巧
2021/05/21 Python
详解nginx进程锁的实现
2021/06/14 Servers
HTML5 新增内容和 API详解
2021/11/17 HTML / CSS