Что такое шаблон проектирования Factory в PHP?
Вопрос
Это сбивает меня с толку, говоря самыми простыми словами, что это делает?Представьте, что вы объясняете это своей матери или кому-то еще, почти пожалуйста.
Решение
Фабрика создает объект.Итак, если вы хотели построить
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();
Реальное преимущество заключается в том, что вы хотите изменить класс.Допустим, мы хотели перейти в другой класс.:
class Factory_New extends Factory{
public function buildC(){
return new ClassD;
}
}
или новый класс b:
class Factory_New2 extends Factory{
public function buildB(){
return new ClassE;
}
}
Теперь мы можем использовать наследование, чтобы легко изменить способ создания класса, чтобы добавить другой набор классов.
Хорошим примером может быть этот класс user:
class User{
public $data;
public function __construct($data)
{
$this->data = $data;
}
}
В этом классе $data
это класс, который мы используем для хранения наших данных.Теперь для этого класса предположим, что мы используем сеанс для хранения наших данных.Фабрика выглядела бы примерно так:
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();
}
}
Фабрики - это шаблон проектирования, который мы используем для управления тем, как мы объединяем объекты, и использование правильных шаблонов фабрик позволяет нам создавать нужные нам индивидуальные объекты.
Другие советы
Как настоящая фабрика, она создает что-то и возвращает это обратно.
Представьте себе что-то вроде этого
$joe = new Joe();
$joe->say('hello');
или фабричный метод
Joe::Factory()->say('hello');
Реализация фабричного метода создаст новый экземпляр и вернет его.
Шаблон проектирования Factory очень хорош, когда вы имеете дело с несколькими ресурсами и хотите реализовать высокоуровневую абстракцию.
Давайте разберем это на отдельные разделы.
Предположим, вам нужно реализовать абстракцию, и пользователю вашего класса не нужно заботиться о том, что вы реализовали в определении класса.
Ему / ей просто нужно побеспокоиться об использовании методов вашего класса.
например ,У вас есть две базы данных для вашего проекта
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;
}
}
Ваш фабричный класс позаботится о создании объекта для подключения к базе данных.
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
Надеюсь, это поможет.
В общем, "фабрика" что-то производит:в случае объектно-ориентированного программирования "фабричный шаблон проектирования" создает объекты.
Не имеет значения, написано ли это на PHP, C # или любом другом объектно-ориентированном языке.
Заводской шаблон дизайна (Factory Pattern) предназначен для свободного соединения.Подобно значению factory, передача данных на фабрику (производство данных) конечному пользователю.Таким образом, фабрика разрывает тесную связь между источником данных и процессом обработки данных.
Фабрика просто генерирует объект или объекты.
Возможно, у вас есть фабрика, которая создает соединение с MySQL.
Этот ответ связан с другим сообщением, в котором Дэниел Уайт сказал использовать factory для создания соединения с MySQL с использованием шаблона factory.
Для подключения к MySQL я бы предпочел использовать шаблон singleton, поскольку вы хотите использовать то же соединение для доступа к базе данных, а не создавать другое.
Классическим подходом к созданию экземпляра объекта является:
$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()).
В этом больше нет необходимости, можно отправить "Product" или "Customer" (точные названия существующих классов) в качестве значения переменной для динамического создания экземпляра:
$classname='Product';
$Object1=new $classname; //this will instantiate new Product()
$classname='Customer';
$Object2=new $classname; //this will instantiate new Customer()
Для справки, простыми словами, фабрика, как сказал @Pindatjuh, возвращает объект.
Итак, в чем разница с конструктором?(это делает то же самое)
- конструктор использует свой собственный экземпляр.
- Что-то я хочу сделать что-то более продвинутое, и я не хочу раздувать объект (или добавлять зависимости).
Конструктор вызывается при создании каждого экземпляра.Иногда ты этого не хочешь.
Например, предположим, что каждый раз, когда я создаю объект класса 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;
}