关于php:这是工厂模式的工作原理吗?

Is this how the Factory Pattern works?

单例模式和注册模式对我来说非常简单,很容易理解,但是工厂模式一直是我还不能让我的大脑100%解释的东西。我想我现在可以理解了,我在下面写了一个示例代码,请检查并告诉我这是否是工厂模式的正确使用。示例在PHP中…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?php
 /**
 *   Factory.class.php
 */

class Factory {
    public static $_database;
    public static $_cache;
    public static $_session;

    // Build our User object with all it's dependencies  
    public static function makeUserObject()
    {
        $user = new User();
        $user->setDatabaseObject(self::$_database);
        $user->setCacheObject(self::$_cache);
        $user->setSessionObject(self::$_session);
        return $user;
    }

    // other objects will be here someday......
}

/**
 *  User.class.php
 */

class User
{
    public function __construct() { }

    // inject Database Object
    public function setDatabaseObject($databaseConnectionObject)
    {
        $this->_databaseObject = $databaseConnectionObject;
    }

    // inject Cache Object
    public function setCacheObject($cacheObject)
    {
        $this->_cacheObject = $cacheObject;
    }

    // inject Session Object
    public function setSessionObject($sessionObject)
    {
        $this->_sessionObject = $sessionObject;
    }

    // other methods here for User object...........
}

/**
 *  index.php  Main page that puts it all together
 *  assume that classes are autoloaded into this page already
 */

// Set our Database + Cache + Session objects into the Factory Object
Factory::$_database = new Databse();
Factory::$_cache = new Cache();
Factory::$_session = new Session();

// Create our User object
// The factory class will build the User object and inject all
// it's dependencies for us =)
$user = Factory::makeUserObject();

?>

因此,基本上,数据库、缓存和会话对象都是被创建的(这里没有显示),然后它们被添加到工厂对象中,我可以在工厂类中为每个需要这3个依赖项中的任何一个的对象构建一个方法,我也可以设置它们得到的依赖项。这也使得单个类仍然可以移植,因为如果不需要工厂对象,我可以直接在那里注入依赖项。这听起来对吗?如果这是对的,这听起来真的很有用

更新第1号

这是基于这里我在这里读到的一篇博客文章http://www.potstuck.com/2009/01/08/php-dependency-injection/他们把它称为"工厂",我一直在使用一个注册表,很多人一直在告诉我要调查一个"工厂",我读到的关于它的所有信息直到我读到这篇文章,才点击我的大脑,但看起来它不是一个"因素"。"?"

更新第2号来自维基百科http://en.wikipedia.org/wiki/factory_object在面向对象的计算机编程中,工厂对象是用于创建其他对象的对象。它是一个构造函数的抽象,可以用来实现各种分配方案,例如单例模式。工厂对象通常对它能够创建的每种对象都有一个方法。这些方法可以选择接受定义如何创建对象的参数,然后返回创建的对象。工厂对象用于获取特定类型的对象比简单地创建新对象更复杂的过程的情况。工厂对象可能会决定动态地创建对象的类(如果适用),从对象池返回它,对对象进行复杂的配置,或者其他事情。

所以也许这在某种程度上是一个"工厂对象"…


从下面的问题总结和扩展我的意见

正如其他人所说,它不是一个工厂,仅仅是因为不存在具有这个名称的模式。它要么是抽象工厂,要么是工厂方法,尽管从实用主义角度来说,人们经常提到工厂,或者只是说工厂,这对我来说没问题。

会话、缓存和数据库通常是在应用程序流的早期初始化的,所以这基本上是引导工作。我觉得您要找的不是对象的创建,而是对象在整个应用程序中的处理。这和工厂做什么有点不同。

正如我在评论中所说,仅仅因为它不是一个因素,不管怎样,并不意味着你的代码是坏的。如果它能解决你的问题,那就很酷了。但我仍然认为,您正在尝试做的工作(例如,在运行时创建和管理资源)最好与DI服务容器一起使用。

如果您现在不想使用DI容器来实现这一点,您可以看看Zend_应用程序以及它们如何引导资源。这是一个替代方案,可以稍后添加DI容器。

事实上,以前问题中的许多主题已经在Zend框架中解决了,例如config类。我不是说用ZF,但你可以看看他们是怎么做的。当然,您也可以查看其他框架。

一些包含PHP示例的模式站点:

  • http://sourcemaking.com/creational_模式
  • http://www.fluffycat.com/php-design-patterns/
  • http://www.ibm.com/developerworks/library/os-php-designptrns/?S&T=105AGX44&S&U CMP=艺术
  • http://www.ibm.com/developerworks/opensource/library/os-php-designpatterns/index.html?Ca=DRS—TP1308


这就是工厂模式,但是您可能需要一个更好的命名约定,而不仅仅是称它为Factory。它还包含依赖注入的痕迹。

虽然从技术上讲可以称之为工厂模式,但这可能不是一个很好的模式用法。工厂是一种创造性的模式,它封装了直接引用类名和对象创建的代码,如精确的构造函数参数等。要获得最佳结果,请在设计类和工厂时记住这一点。

例如,stackoverflow根据用户的信誉评分为用户提供不同的权限。假设它可以有以下类型的用户:

1
2
3
4
5
6
NewbieUser      [1-100]
BeginnerUser    [101-1000]
AverageJoeUser  [1001-5000]
VeteranUser     [5001-20000]
PowerUser       [20001-50000]
GodModeUser     [50001-100000]

可以通过查找用户的rep.并通过直接引用类实例化相应的用户对象来创建用户。乔恩斯基特不会出现在任何类别,以防你想知道。下面是一个带有直接实例化的糟糕实现:

1
2
3
if(reputation >= 1001 and reputation <= 5000) {
    AverageJoeUser user = new AverageJoeUser();
}

如果以后我们要更改类名或用户的实例化方式,则必须找到并更改创建对象的每个此类实例。如果你问我的话,我做了很多工作。相反,如果我们在这里使用了工厂模式,那么更改将以工厂类内的单个方法进行。

1
2
3
4
5
class UserFactory {
    public static User createUser(Integer reputation) {
        ...
    }
}


在我看来不是一个工厂-可能是一个由内而外的建筑商?0;

工厂是一种隐藏实现和实例化的方法。通常会进行一些组装,但简而言之……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  public interface IUser
    {
        void DoSomething();
    }

    public class DumbUser : IUser
    {

        public void DoSomething()
        {
            // duh... what should i do?
        }

    }

    public class SmartUser : IUser
    {

        public void DoSomething()
        {
            // calclulating prime numbers while baking bread
        }

    }


    public class UserFactory
    {
        public static IUser CreateUser()
        {
            Random r = new Random(Environment.TickCount);

            return r.Next(10) > 5 ? (IUser) new SmartUser() : new DumbUser();
        }
    }

    public class YourProgram
    {
        public void Run()
        {
            IUser user = UserFactory.CreateUser();
            user.DoSomething();
        }
    }


因为看起来你只是想创建一个用户,我不认为需要一个抽象的因素,从今以后简单地称为工厂。工厂的概念是创建实现特定接口的对象。您希望能够实例化同一接口的两个不同实现。重点是,您可能需要一遍又一遍地创建这些对象,并且在整个代码中将它从objecta更改为objectb是很麻烦的。更换工厂很容易,因为它通常是单件的。

工厂方法的思想与框架相关:您希望在某些框架代码中创建一个用途,但实际的用户实现是在派生类中,也就是说,框架的用户正在编写自己的应用程序,也就是说,当您需要告诉框架的用户"现在创建用户对象",这是对工厂方法的调用。用户必须实现这一点。根据gof的说法,它也被称为虚拟contstructor。

构建器通常在对象有不同的表示形式时使用,但实际上并非如此。在我看来,缓存、数据库和会话可以作为单例实现,从而减轻了所涉及的复杂性。否则,我建议您使用一个服务定位器,它允许您使用GetDatabaseGetSession等。然后,您必须在创建时将定位器传递给用户对象(以及许多其他对象)。好处是,这个定位器可以跨不同的类重用。


在我看来更像建设者模式。你说的工厂模式是指工厂模式还是工厂模式?然而,它们都处理继承,而您的代码只是组装一个"复杂"的对象。