Шаблон проектирования: Фабрика

Фабричный метод, фабрика или виртуальный конструктор – это все шаблон проектирования, который предоставляет интерфейс для создания объектов имеющих схожие свойства своим подклассам.

Грубо говоря, фабричный метод – это обычный метод класса, который возвращает объекты при обращении к нему (создавая их при этом). Такой прием, в основном, используется для унификации архитектуры системы. Как следствие этого – объекты, порожденные фабричным методом, имеют одинаковые интерфейсы.

На практике это выглядит так:

…
$carsFactory = new CarsFactory;
$cars['toyota'] = $carsFactory->createCar('toyota');
$cars['bmw'] = $carsFactory->createCar('bmw');
foreach ($cars as $mod => $obj) {
	echo 'Max speed: '.$obj->getMaxSpeed().'';
	echo 'Weight: '.$obj->getWeight();
}
…

Реализуется такой механизм довольно просто:

<?php
class CarsFactory {
	function createCar($brand) {
		$car_obj = 0;
		switch ($brand) {
			case 'toyota': $car_obj = new Toyota;
			case 'bmw':    $car_obj = new Bmw;
			default:       $car_obj = new Toyota;
		}	
		return $car_obj;
	}
}
abstract class Car {
	abstract function getMaxSpeed();
	abstract function getWeight();
}
class Toyota extends Car {
	...
	public function getMaxSpeed() {
		...
	}
}
?>

Буду рад, если кто-нибудь поделится опытом и расскажет, в каких ситуациях этот шаблон применял. А мне добавить тут особо и нечего. Поэтому все :)

Удачи.





Читайте также:



7 Ответов на “Шаблон проектирования: Фабрика”

  1. Гораздо интереснее было бы, если бы вы привели пример класса-фабрики, который может создавать объекты не только по списку, а произвольные.
    Да и в общем, не вижу в этом шаблоне особого смысла, почему не использовать интерфейсы если так уже надо унифицировать классы?

  2. cryptus

    > Гораздо интереснее было бы, если бы вы привели пример класса-фабрики, который может создавать объекты не только по списку, а произвольные.

    Не совсем понял - что значит произвольные? Преобразовать параметр, переданный фабричному методу в инициализацию какого-класса можно разными способами. Но если классы будут разными, то и инициализировать их нужно будет по-разному - это ограничивает как бы область применения (нельзя поэтому совсем уж разные классы порождать через это дело).

    > Да и в общем, не вижу в этом шаблоне особого смысла, почему не использовать интерфейсы если так уже надо унифицировать классы?

    В примере с машинами, унификация классов - это скорее следствие унификации способа порождения объектов. Т.е. основное назначение шаблона фабричный метод - унификация способа порождения схожих объектов. Пример можно глянуть в классе Zend_DB фреймворка Zend - там этот прием используется для генерации разных адаптеров для БД.

  3. И всё таки. Как избавиться от жёстко заданного списка классов.

    Например, если я в будущем захочу приинклудить класс Mersedes, но чтобы не изменять код CarsFactory

  4. Думаю, гораздо более абстрактно будет использовать, пардон, абстрактную фабрику:
    class CarsFactory {

    function createCar($brand) {

    $car_obj = null;

    $brand = ucfirst(strtolower($brand));
    if(class_exists($brand))
    $car_obj = new $brand;

    return $car_obj;
    }
    }

    Это частично решит и проблему “жестко заданных классов”

  5. В kohana-фреймворке factory-паттерн используется повсюду: $this->content = View::factory(‘layoutes/index’)->set(‘title’, ‘Test title’);
    $cars = ORM::factory(‘car’)->find_all();
    Для chain-вызова методов в основном, красиво получается в итоге :)

  6. DEM

    Делал почти так же, только без SWIТCH. Решил немного изменить свою версию и наконец-то разместить на своём блоге, вот что получилось:

    text = $name; //присваиваем переменной $text класса значение параметра $name
    }

    public function myGetText()
    {
    return $this->text; //Возвращаем переменную $text
    }

    }

    class MyClass2 extends ABSTR //Наш второй класс
    {

    public function myGetText()
    {
    return “MyClass2″; //возвращаем текст
    }

    }

    $Factory = new Factory; //Создаём наш объект
    $arr_obj = array(); //Массив в котором будут храниться наши объекты
    $arr_obj[‘mc1′] = $Factory->create(‘MyClass1′, ‘Text’); //засовываем в элемента `mc1` массива $arr_obj новый объект (MyClass1) с параметром `Text`
    $arr_obj[‘mc2′] = $Factory->create(‘MyClass2′); //засовываем в элемента `mc2` массива $arr_obj новый объект (MyClass2) без параметра

    echo $arr_obj[‘mc1′]->myGetText(); //Выводим текст из нашего первого объекта
    echo “”;
    echo $arr_obj[‘mc2′]->myGetText(); //Выводим текст из нашего второго объекта
    ?>

  7. xd

    szc
    dc
    sdc
    sdc
    sd
    cs


© Copyright. . I-Novice. All Rights Reserved. Terms | Site Map