Так работает фабричный шаблон? - PullRequest
8 голосов
/ 26 января 2010

Шаблоны Singleton и Registry были очень просты и понятны для меня сразу, но шаблон Factory был тем, что я до сих пор не мог заставить свой мозг интерпретировать на 100%.Я думаю, что могу понять это сейчас, я написал пример кода ниже, пожалуйста, просмотрите и скажите мне, правильно ли это использовать шаблон Factory.Пример в 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();

?>

Итак, в основном объекты Database, Cache и Session создаются (здесь не показаны), а затем добавляются в объект Factory, я могу создать метод вФабричный класс для каждого объекта, которому потребуется любая из этих 3-х зависимостей, и я могу указать, какие из них они тоже получают.Это также делает его тем, что отдельные классы могут все еще быть несколько переносимыми, так как я могу напрямую вводить туда зависимости, если бы я хотел без фабричного объекта.Это звучит правильно?Если это правильно, это звучит действительно полезно


ОБНОВЛЕНИЕ # 1

Это основано на этом здесь сообщении в блоге, которое я прочитал здесь http://www.potstuck.com/2009/01/08/php-dependency-injection/ они называют это "фабрикой", я использую Реестр, и многие люди говорят мне, чтобы я посмотрел на "фабрику", и все, что я прочитал об этом, просто не щелкнуло в моей голове, пока я не прочитал этот artcleно похоже, что это не "фабрика"?


ОБНОВЛЕНИЕ # 2
С wikipedia http://en.wikipedia.org/wiki/Factory_object В объектно-ориентированном компьютерном программировании фабрикаОбъект - это объект для создания других объектов.Это абстракция конструктора, и его можно использовать для реализации различных схем размещения, таких как шаблон синглтона.У фабричного объекта обычно есть метод для каждого вида объекта, который он способен создать.Эти методы необязательно принимают параметры, определяющие способ создания объекта, а затем возвращают созданный объект.Фабричные объекты используются в ситуациях, когда получение объекта определенного вида является более сложным процессом, чем просто создание нового объекта.Заводской объект может решить создать класс объекта (если применимо) динамически, вернуть его из пула объектов, выполнить сложную настройку объекта или выполнить другие действия.

Так что, может быть, это «Заводской объект» в некотором роде ...

Ответы [ 5 ]

6 голосов
/ 26 января 2010

Обобщены и расширены мои комментарии ниже вопроса здесь

Как уже говорили другие, это не Factory , просто потому, что шаблон с таким именем не существует. Это либо AbstractFactory , либо FactoryMethod , хотя прагматично люди часто ссылаются либо на то, либо просто говоря Factory , и это нормально для меня.

Session, Cache и DB - это обычно то, что вы инициализируете на ранней стадии вашего потока приложений, так что это в основном работа по начальной загрузке. У меня сложилось впечатление, что вы ищете не столько создание объектов, сколько их обработка во всем приложении. Это несколько иная проблема, чем то, что делает FactoryWh независимо от .

Как я уже говорил в комментариях, то, что это не просто FactoryWh независимо от , не означает, что ваш код плохой. Если это решит вашу проблему, это круто. Но я все еще думаю, что вы пытаетесь сделать, например, создание и управления ресурсами во время выполнения лучше всего использовать с DI Service Container .

Если вы не хотите использовать DI-контейнер сейчас для этого, вы можете взглянуть на Zend_Application и на то, как они загружают ресурсы . Это альтернатива и оставляет возможность добавить контейнеры DI позже.

На самом деле, довольно много тем в ваших предыдущих вопросах уже решены в Zend Framework, например, Конфиг классы. Я не говорю, использовать ZF, но вы можете проверить это, чтобы увидеть, как они делают вещи. Конечно, вы также можете посмотреть другие рамки .

Некоторые шаблоны сайтов с примерами PHP:

5 голосов
/ 26 января 2010

Это нормальный фабричный шаблон, но вам может потребоваться более хорошее соглашение об именах, чем просто назвать его 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();
}

Если бы позже мы должны были изменить имена классов или методы создания пользователей, каждый такой экземпляр, где был создан объект, должен был бы быть найден и изменен. Довольно много работы, если вы спросите меня. Вместо этого, если бы мы использовали здесь шаблон фабрики, изменение происходило бы в одном методе внутри класса Factory.

class UserFactory {
    public static User createUser(Integer reputation) {
        ...
    }
}
3 голосов
/ 26 января 2010

Мне не кажется, что фабрика - может быть строителем изнутри?; 0)

Фабрика - это способ скрыть реализацию и реализацию. И обычно выполняется какая-то сборка, но в двух словах ...

  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();
        }
    }
2 голосов
/ 26 января 2010

Поскольку кажется, что вы просто хотите создать пользователя, я не вижу необходимости в абстрактном факторе, отныне просто называемом фабрикой. Идея фабрик заключается в создании объектов, которые реализуют определенный интерфейс. Вы хотели бы иметь возможность создавать две разные реализации одного и того же интерфейса. Дело в том, что вам, возможно, придется создавать эти объекты снова и снова, и изменять их с ObjectA на ObjectB по всему коду сложно. Менять фабрику легко, потому что она часто бывает одиночной.

Идея фабричного метода связана с фреймворками: вы хотите создать использование в некотором коде фреймворка, но фактическая пользовательская реализация находится в производных классах, т.е. есть пользователи вашей фреймворк, пишущие свое собственное приложение - именно тогда, когда вам нужно сообщить пользователю вашей структуры "создайте объект пользователя сейчас", который является вызовом фабричного метода. Пользователь должен реализовать это. В соответствии с GoF он также называется Virtual Contstructor.

Конструктор обычно используется, когда существуют разные представления объекта, что на самом деле не так. На мой взгляд, кэш, база данных и сеанс могут быть реализованы как синглтоны, что облегчает сложные сложности. В противном случае я бы предложил использовать ServiceLocator, который позволяет вам GetDatabase, GetSession и т. Д. Затем вам нужно будет передать локатор пользовательскому объекту (и многим другим объектам) при создании. Плюс в том, что этот локатор можно использовать в разных классах.

1 голос
/ 26 января 2010

Для меня это больше похоже на Образец Строителя. Какой фабричный шаблон вы имели в виду, AbtractFactory или FactoryMethod? Тем не менее, они оба имеют дело с наследованием, а ваш код просто собирает «сложный» объект.

...