1. 概念

    工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式。

  2. 好处

    使用工厂模式的好处是,如果你想要更改所实例化的类名等,则只需要更改该工厂方法内容即可,不需要逐一寻找代码中具体实例化的地方(new 处)修改了。为系统结构提供灵活的动态扩展机制,减少了耦合。

  3. 分类

    • 简单工厂模式
    • 工厂方法模式
    • 抽象工厂模式
  • 简单工厂模式

    简单工厂模式又称静态工厂模式,之所以可以这么说,是因为简单工厂模式是通过一个静态方法来创建对象的

    <?php
    class DbMysql
    {
        public function conn()
        {
            echo "连接MySQL";
        }
    }
    
    class DbSqlite
    {
        public function conn()
        {
            echo "连接SQLite";
        }
    }
    
    class DbFactory
    {
     	public static function createIns($type)
        {
            switch ($type) 
            {
                case 'mysql':
                    return DbMysql();
                    break;
                case 'sqlite':
                    return new DbSqlite();
                    break;
                default:
                    throw new ErrorException('类型错误');
            }
    
        }
    }
    
    $mysql = DbFactory::createIns('mysql');
    $mysql->conn();
    
    $sqlite = DbFactory::createIns('sqlite');
    $sqlite->conn();
    
  • 工厂方法模式

    简单工厂模式实现了产品类的代码跟客户端代码的分离,但会有一个问题,优秀的代码是符合“开闭原则”如果你要加一个C类产品,你就要修改工厂类里面的代码,也就是说要增加条件语句如:switch–case。对于这个问题,接下来的工厂方法模式可以解决这个问题。

    1. 概念

      工厂方法就是为配一个产品提供一个独立的工厂类,通过不同的工厂实例来创建不同的产品实例。

    2. 优点

      • 拥有良好的封装性,代码结构清晰,对于每一个对象的创建都是有条件约束的。如:调用一个具体的产品对象,只需要知道这个产品的类名和约束参数就可以了,不用知道创建对象自身的复杂过程。降低模块之间的耦合度。
      • 拥有良好的扩展性,新增一个产品类,只需要适当的增加工厂类或者扩展一个工厂类,如下面的例子中,当需要增加一个数据库Oracle的操作,则只需要增加一个Oracle类,工厂类不用修改任务就可完成系统扩展。
      • 屏蔽产品类,这一特点非常重要,产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化。
    3. 使用场景

      • 支付宝、微信、银联的连接方式(connectMode),支付方式(payMode)。使用工厂模式,“客户”就不需要知道具体的链接方式和支付方式了,只需要调用connectMode和payMode即可。
      • MySQL、SQL Server、Oracle等数据库的连接方式(connectMode)、查询方式(selectMode)等操作可以使用工厂模式进行封装。
      <?php
      //数据库操作接口
      interface Db
      {
          public function conn();
      }
      
      class DbMysql implements Db
      {
          public function conn()
          {
              echo "链接MySQL";
          }
      }
      
      class DbSqlite implements Db
      {
          public function conn()
          {
              echo "连接SQLite";
          }
      }
      
      //工厂接口
      interface Factory
      {
          public static function createIns();
      }
      
      class MysqlFactory implements Factory
      {
          public static function createIns()
          {
              return new DbMysql();
          }
      }
      
      class SqliteFactory implements Factory
      {
          public static function createIns()
          {
              return new DbSqlite();
          }
      }
      
      //客户端
      $mysql = MysqlFactory::createIns();
      $mysql->conn();
      $sqlite = SqliteFactory::createIns();
      $sqlite->conn();
      
  • 抽象工厂模式

    1. 概念

      抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象,而且使用抽象工厂模式还要满足以下条件:

      • 系统中有多个产品族,而系统一次只可能消费其中一族产品
      • 同属于同一产品族的产品可以使用
      • 产品族:位于不同产品等级结构中,功能相关联的产品组成的家族。下面例子的汽车和空调就是两个产品树,奔驰C200+格力某型号空调就是一个产品族,同理,奥迪A4+海尔某型号空调也是一个产品族。
      <?php
      //汽车(抽象产品接口)
      interface AutoProduct
      {
          public function dirve();
      }
      
      class AudiA4Product implements AutoProduct 
      {
          public function dirve()
          {
              echo '奥迪A4';
          }
      }
      
      class BenzC200Product implements AutoProduct
      {
          public function dirve()
          {
              echo '奔驰C200';
          }
      }
      
      //空调(抽象产品接口)
      interface AirCondition
      {
          public function blow();
      }
      
      class GreeAirCondition implements AirCondition
      {
          public function blow()
          {
              echo '格力';
          }
      }
      
      class HaierAirCondition implements AirCondition
      {
          public function blow()
          {
              echo '海尔';
          }
      }
      
      //工厂接口
      interface Factory
      {
          public static function getAuto();
          public static function getAirCondition();
      }
      
      //工厂A 奥迪A4+海尔空调
      class AFactory implements Factory
      {
          public static function getAuto()
          {
              return new AudiA4Product();
          }
          public static function getAirCondition()
          {
              return new HaierAirCondition();
          }
      }
      
      //工厂B 奔驰+格力
      class BFactory implements Factory
      {
          public static function getAuto()
          {
              return new BenzC200Product();
          }
          public static function getAirCondition()
          {
              return new GreeAirCondition();
          }
      }
      
      //客户端
      //A工厂制作车
      $auto_carA = AFactory::getAuto();
      $auto_airA = AFactory::getAirCondition();
      
      //奥迪+空调
      $auto_carA->dirve();
      $auto_airA->blow();
      
  • 三种工厂模式的比较

    • 简单工厂:用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
    • 工厂方法:用来生产同一等级结构中的固定产品。(支持增加任意产品)
    • 抽象工厂:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)