106

这让我很困惑,用最简单的术语来说,它有什么作用?假装你正在向你的母亲或几乎请的人解释。

4

10 回答 10

190

工厂创建一个对象。所以,如果你想建立

 class A{
    public $classb;
    public $classc;
    public function __construct($classb, $classc)
    {
         $this->classb = $classb;
         $this->classc = $classc;
    }
  }

您不希望每次创建对象时都必须执行以下代码

$obj = new ClassA(new ClassB, new Class C);

那就是工厂的用武之地。我们定义了一个工厂来为我们处理这个问题:

class Factory{
    public function build()
    {
        $classc = $this->buildC();
        $classb = $this->buildB();
        return $this->buildA($classb, $classc);

    }

    public function buildA($classb, $classc)
    {
        return new ClassA($classb, $classc);
    }

    public function buildB()
    {
        return new ClassB;
    }

    public function buildC()
    {
        return new ClassC;
    }
}

现在我们要做的就是

$factory = new Factory;
$obj     = $factory->build();

真正的优势是当您想更改课程时。假设我们想传入一个不同的 ClassC:

class Factory_New extends Factory{
    public function buildC(){
        return new ClassD;
    }
}

或新的 B 类:

class Factory_New2 extends Factory{
    public function buildB(){
        return new ClassE;
    }
}

现在我们可以使用继承来轻松修改类的创建方式,以放入一组不同的类。

一个很好的例子可能是这个用户类:

class User{
    public $data;
    public function __construct($data)
    {
        $this->data = $data;
    }
}

在这个类$data中是我们用来存储数据的类。现在对于这个类,假设我们使用 Session 来存储我们的数据。工厂看起来像这样:

class Factory{
    public function build()
    {
        $data = $this->buildData();
        return $this->buildUser($data);
    }

    public function buildData()
    {
        return SessionObject();
    }

    public function buildUser($data)
    {
        return User($data);
    }
}

现在,假设我们想要将所有数据存储在数据库中,更改它真的很简单:

class Factory_New extends Factory{
    public function buildData()
    {
        return DatabaseObject();
    }
}

工厂是我们用来控制如何将对象放在一起的设计模式,使用正确的工厂模式可以让我们创建我们需要的定制对象。

于 2010-01-18T01:37:34.533 回答
27

当您处理多个资源并希望实现高级抽象时,工厂设计模式非常好。

让我们把它分成不同的部分。

假设您必须实现抽象并且您的类的用户不需要关心您在类定义中实现了什么。

他/她只需要担心你的类方法的使用。

例如,您的项目有两个数据库

class MySQLConn {

        public function __construct() {
                echo "MySQL Database Connection" . PHP_EOL;
        }

        public function select() {
                echo "Your mysql select query execute here" . PHP_EOL;
        }

}

class OracleConn {

        public function __construct() {
                echo "Oracle Database Connection" . PHP_EOL;
        }

        public function select() {
                echo "Your oracle select query execute here" . PHP_EOL;
        }

}

您的 Factory 类将负责为数据库连接创建对象。

class DBFactory {

        public static function getConn($dbtype) {

                switch($dbtype) {
                        case "MySQL":
                                $dbobj = new MySQLConn();
                                break;
                        case "Oracle":
                                $dbobj = new OracleConn();
                                break;
                        default:
                                $dbobj = new MySQLConn();
                                break;
                }

                return $dbobj;
        }

}

用户只需要传递数据库类型的名称

$dbconn1 = DBFactory::getConn("MySQL");
$dbconn1->select();

输出:

MySQL Database Connection
Your mysql select query execute here

将来您可能有不同的数据库,那么您不需要更改整个代码只需要传递新的数据库类型,其他代码将在不进行任何更改的情况下运行。

$dbconn2 = DBFactory::getConn("Oracle");
$dbconn2->select();

输出:

Oracle Database Connection
Your oracle select query execute here

希望这会有所帮助。

于 2018-04-25T06:28:10.030 回答
21

就像现实生活中的工厂一样,它创造一些东西并返回它。

想象这样的事情

$joe = new Joe();
$joe->say('hello');

或工厂方法

Joe::Factory()->say('hello');

工厂方法的实现将创建一个新实例并返回它。

于 2010-01-18T01:31:28.293 回答
2

实例化对象的经典方法是:

$Object=new ClassName();

PHP 能够使用以下语法从变量名动态创建对象:

$Object=new $classname;

其中变量 $classname 包含要实例化的类的名称。

所以经典的对象分解看起来像:

function getInstance($classname)
{
  if($classname==='Customer')
  {
    $Object=new Customer();
  }
  elseif($classname==='Product')
  {
    $Object=new Product();
  }
  return $Object;
}

如果您调用 getInstance('Product') 函数,该工厂将创建并返回 Product 对象。否则,如果您调用 getInstance('Customer') 函数,该工厂将创建并返回 Customer 类型对象(从 Customer() 类创建)。

不再需要这样了,可以发送“产品”或“客户”(现有类的确切名称)作为动态实例化的变量值:

$classname='Product';
$Object1=new $classname; //this will instantiate new Product()

$classname='Customer';
$Object2=new $classname; //this will instantiate new Customer()
于 2014-09-14T12:41:03.897 回答
1

一般来说,“工厂”会产生一些东西:在面向对象编程的情况下,“工厂设计模式”会产生对象。

它是 PHP、C# 还是任何其他面向对象的语言都没有关系。

于 2010-01-18T01:31:50.463 回答
1

工厂设计模式(Factory Pattern)是针对松散耦合的。就像工厂的意思一样,数据到工厂(生产数据)到最终用户。通过这种方式,工厂打破了数据源和数据过程之间的紧密耦合。

于 2013-06-17T11:22:32.820 回答
0

工厂只是生成一个或多个对象。

您可能有一个建立 MySQL 连接的工厂。

http://en.wikipedia.org/wiki/Factory_method_pattern

于 2010-01-18T01:30:56.920 回答
0

这个答案与 Daniel White 所说的使用工厂模式使用工厂模式创建 MySQL 连接的其他帖子有关。

对于 MySQL 连接,我宁愿使用单例模式,因为您想使用相同的连接来访问数据库而不是创建另一个。

于 2014-04-09T13:30:14.283 回答
0

为了记录,简单地说,像@Pindatjuh 所说的工厂返回一个对象。

那么,构造函数有什么区别呢?(也一样)

  1. 构造函数使用他自己的实例。
  2. 我想要一些更高级的东西,我不想让对象膨胀(或添加依赖项)。
  3. 创建每个实例时都会调用构造函数。有时你不希望那样。

    例如,假设每次创建 Account 类的对象时,我都会从数据库中读取一个文件并将其用作模板。

使用构造函数:

class Account {
      var $user;
      var $pwd;
      var ...
      public __construct() {
         // here i read from the file
         // and many other stuff
      }
}

使用工厂:

class Account {
      var $user;
      var $pwd;
      var ...
}
class AccountFactory {
      public static Create() {
         $obj=new Account();
         // here we read the file and more stuff.
         return $obj;
      }
于 2016-03-26T21:33:07.187 回答
0

当涉及到您的应用程序代码时,工厂是一种易于维护和可扩展的解决方案。它解决了 SOLID 建议我们遵循的代码耦合问题。本质上是一种简化结构构建/创建的方法。它可以是一个对象、一个函数、一个数组。

只要您将使用结构的代码与创建它们的代码分离并返回对象/结构,您就可以使用可以是以下四个之一的工厂:

  • 工厂方法
  • 抽象工厂
  • 静态工厂
  • 简易工厂

主要区别在于工厂方法和抽象工厂。

一个从定义明确的元素列表中生成对象/结构,另一个使用自己的分解策略生成对象的蓝图。

一个生成具体元素,另一个生成类型。

于 2021-02-07T22:24:43.673 回答