开发者

Is this how the Factory Pattern works?

The Singleton and the Registry patterns were very simple and easy for me to understand right away but the Factory pattern has been something I haven't been able to get my brain to interpret 100% yet. I think I might understand it now, I have wrote a sample code below, please review and tell me if this is the proper use of the Factory pattern. Sample is in 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();

?>

So basicly the Database, Cache, and Session objects are created (not shown here) then they are added to the Factory object, I the can build a method in the factory class for each object that will need any of these 3 dependencies and I can set which ones they get too. This also makes it where the individual classes can still be somewhat portable as I can directly inject there dependencies if I wanted to without the factory object. Does this sound right? If this is right, this sounds really useful


UPDATE # 1

This is based off this here a blog post I read here http://www.potstuck.com/2009/01/08/php-dependency-injection/ they refer to it as a "factory", I been using a Registry and a lot of people keep telling me to look into a "factory" and everything I read about it just didn't click in my head until I read this artcle but looks like it isn't a "factory"?


UPDATE # 2

From wikipedia http://en.wikipedia.org/wiki/Factory_object In object-oriented computer programming, a factory object is an object for creating other objects. It is an abstraction of a constructor, and can be used to implement various allocation schemes, such as the singleton pattern. A factory object typically has a method for every kind of object it is capable of creating. These methods optionally accept parameters defining how the object is created, and then return the created object. Factory objects are used in si开发者_开发知识库tuations where getting hold of an object of a particular kind is a more complex process than simply creating a new object. The factory object might decide to create the object's class (if applicable) dynamically, return it from an object pool, do complex configuration on the object, or other things.

So maybe this is a "Factory Object" in a way afterall...


Summarized and extended my comments from below the question here

Like others said, it is not a Factory, simply because a pattern with this name does not exist. It's either an AbstractFactory or a FactoryMethod, though pragmatically people often refer to either or by just saying Factory and that's fine with me.

Session, Cache and DB are usually something you will initialize early in your application flow, so this is basically bootstrap work. I get the impression what you are looking for is not so much the creation of objects, but their handling throughout the application. That's a somewhat different concern from what a FactoryWhatever does.

Like I said in the comments, just because it isnt exactly a FactoryWhatever, doesn't mean that your code is bad. If it solves your problem, it's cool. But I still think, what you are trying to do, e.g. creating and managing resources at runtime is best used with a DI Service Container.

If you don't want to use a DI Container now for this, you could have a look at Zend_Application and how they bootstrap resources. It's an alternative and leaves the possibility to add DI containers later.

In fact, quite a lot of the topics in your previous questions have been solved in Zend Framework already, e.g. Config classes. I am not saying use ZF, but you could check it out to see how they do things. Of course, you can look at the other frameworks too.

Some pattern sites with PHP examples:

  • http://sourcemaking.com/creational_patterns
  • http://www.fluffycat.com/PHP-Design-Patterns/
  • http://www.ibm.com/developerworks/library/os-php-designptrns/?S_TACT=105AGX44&S_CMP=ART
  • http://www.ibm.com/developerworks/opensource/library/os-php-designpatterns/index.html?ca=drs-tp1308


That is the factory pattern alright, but you might need a better naming convention than just calling it Factory. Also it contains traces of dependency injection.

Though you could technically call it the factory pattern, it's probably not a good usage of the pattern. Factory is a creational pattern that encapsulates your code from directly referencing class names and object creation as in exact constructor parameters etc. To get the best results, keep that in mind while designing your classes and factories.

For example, StackOverflow gives users different rights depending on their reputation score. Hypothetically speaking, it could have the following types of users:

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

and a user could be created by looking up their rep. and instantiating the corresponding user object by directly referencing the class. Jon Skeet does not appear in any category in case you're wondering. Here's a crappy implementation with direct instantiation:

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

If later down the road we were to change the class names or the way users were instantiated, every such instance where the object was created would have to be found and changed. Quite a lot of work if you ask me. Instead, if we had used the Factory pattern here, the change would go in a single method inside the Factory class.

class UserFactory {
    public static User createUser(Integer reputation) {
        ...
    }
}


Does't look like a factory to me - could be an inside-out builder?;0)

Factory is a way of hiding implementation and instantiation. And there is usually some assembly being done, but in a nutshell....

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


Since it seems you simply want to create a User, I don't see the need for an abstract factor, henceforth simply referred to as factory. The idea of factories is to create objects that implement a certain interface. You'd want to be able to instantiate two different implementation of the same interface. The point is that you may have to create these objects over and over, and changig it from ObjectA to ObjectB all over the code is cumbersome. Exchanging the factory is easy, because it often is a singleton.

The factory method's idea is related to frameworks: You want to create a use in some framework code, but the actual user implementation is in derived classes, i.e. there are users of your framework writing their own app - that is when you need to tell the user of you framework "create a user object now", which is a call to the factory method. The user must implement this. It's also called a Virtual Contstructor according to GoF.

The builder is typically used when there are different representations of the object, which is not really the case here. In my eyes, cache, database and session could be implemented as singletons, thus easing up the intricacies involved. Otherwise, I would suggest using a ServiceLocator which allows you to GetDatabase, GetSession, etc. Then, you'd have to pass the locator to user object (and many other objects) on creation. The upside is that this locator can be reused across different classes.


Looks more like the Builder Pattern to me. Which factory pattern did you actually mean, AbtractFactory or FactoryMethod? However, they both deal with inheritance and you code just assembles a "complex" object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜