代码之家  ›  专栏  ›  技术社区  ›  JasonDavis

工厂模式就是这样运作的吗?

  •  8
  • JasonDavis  · 技术社区  · 15 年前

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

    <?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();
    
    ?>
    


    更新#1

    这是基于我在这里读到的一篇博文 http://www.potstuck.com/2009/01/08/php-dependency-injection/ 他们把它称为“工厂”,我一直在使用一个注册表,很多人一直告诉我去调查一个“工厂”,我读到的关于它的所有东西在我读到这篇文章之前都没有在我的脑海中闪现,但看起来它不是一个“工厂”?


    更新#2
    从…起 wikipedia http://en.wikipedia.org/wiki/Factory_object 在面向对象的计算机编程中,工厂对象是用于创建其他对象的对象。它是构造函数的抽象,可用于实现各种分配方案,如单例模式。 Factory对象用于获取特定类型对象的过程比创建新对象更复杂的情况。工厂对象可能决定动态创建对象的类(如果适用)、从对象池返回、对对象进行复杂配置或其他操作。

    5 回复  |  直到 15 年前
        1
  •  6
  •   Gordon Haim Evgi    15 年前

    总结并扩展了我对以下问题的评论

    正如其他人所说,这不是一个好主意 工厂 ,这仅仅是因为不存在具有此名称的模式。要么是一个 或者 ,尽管从实用角度来看,人们通常指的是“或”或“只是说” 工厂

    会话、缓存和数据库通常是在应用程序流的早期初始化的,所以这基本上是引导工作。我得到的印象是,你要找的不是那么多 创造 在整个应用程序中。这是一个有点不同的关注,从什么样的 工厂

    工厂 ,并不意味着您的代码不好。如果它解决了你的问题,那很酷。但我仍然认为,你正在尝试做什么,例如创造 在运行时管理资源最好与 DI Service Container

    如果您不想使用DI容器 对于这个,你可以看看 Zend_Application and how they bootstrap resources . 这是另一种选择,让我们有可能 add DI containers later.

    事实上,您前面问题中的很多主题已经在Zend框架中解决了,例如配置类。我不是说使用ZF,但你可以查看它,看看它们是如何工作的。当然,你可以看看 other frameworks

        2
  •  5
  •   Community CDub    8 年前

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

    虽然从技术上讲,您可以称之为工厂模式,但它可能不是该模式的良好用法。Factory是一种创造性的模式,它通过直接引用类名和对象创建来封装代码,就像在精确的构造函数参数中一样。要获得最佳结果,请在设计类和工厂时牢记这一点。

    例如 StackOverflow 根据用户的声誉分数为用户提供不同的权限。假设说,它可能有以下类型的用户:

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

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

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

    class UserFactory {
        public static User createUser(Integer reputation) {
            ...
        }
    }
    
        3
  •  3
  •   Sky Sanders    15 年前

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

      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();
            }
        }
    
        4
  •  2
  •   mnemosyn    15 年前

    由于您似乎只是想创建一个用户,因此我不认为有必要使用抽象的因素,即工厂。工厂的思想是创建实现特定接口的对象。您希望能够实例化同一接口的两个不同实现。关键是,您可能需要一遍又一遍地创建这些对象,并且在整个代码中将其从ObjectA更改为ObjectB是很麻烦的。交换工厂很容易,因为它通常是一个单身汉。

    当对象有不同的表示形式时,通常使用生成器,但这里的情况并非如此。在我看来,缓存、数据库和会话可以作为单例实现,从而简化了复杂的操作。否则,我建议使用ServiceLocator,它允许您 GetDatabase , GetSession 然后,在创建时必须将定位器传递给用户对象(和许多其他对象)。好处是这个定位器可以跨不同的类重用。

        5
  •  1
  •   bertolami    15 年前

    在我看来更像是构建器模式。你实际上指的是哪种工厂模式,AbtractFactory还是FactoryMethod?然而,它们都处理继承,而您的代码只是组装一个“复杂”对象。