Понимание шаблонов проектирования и ООП в PHP
Я новичок в php и пытаюсь учиться. У меня есть 2 одинаковых класса. Я хочу создать эти объекты, когда я передаю количество и тип объекта. Я читал немного о заводском образце. Вот мой заводской класс:
class AssetFactory
{
private static $table;
public static $objects = array();
public static function Create($asset,$count)
{
switch ($asset) {
case "Item":
self::$table = "items";
break;
case "Job":
self::$table = "jobs";
break;
}
$db = new Database();
$rows = $db->query("SELECT * FROM ".self::$table." LIMIT ".$count);
foreach($rows as $row)
{
self::$objects[] = new $asset($row);
}
return self::$objects;
}
}
и когда мне нужно 5 предметов, я использую:
$myItems = AssetFactory::Create('Item',5);
когда мне нужны работы, я использую:
$myJobs= AssetFactory::Create('Job',5);
предмет и работа - это те же классы. Мой вопрос здесь, как я уже сказал, я пытаюсь учиться. Я делаю это правильно? Правильно ли я понял фабричный образец? Есть хорошие документы по этому поводу (я прочитал все на php.net, получил что-нибудь еще).
2 ответа
Есть несколько вещей, которые кажутся неправильными в этом случае.
Прежде всего, есть две подобные структуры, которые используются для создания объекта:
- фабрики: если объект требует какой-либо инициализации перед его выпуском для "потребления"
- строители: если перед созданием объекта вы должны создать кучу других объектов
Обычно люди не делают различий между ними, а просто называют их "фабриками". Так что это будет два случая, когда вы используете фабрику.
То, что у вас есть сейчас, не подходит под описание. Вы создаете какое-то соединение с базой данных, затем получаете некоторые данные и затем используете их для создания списка объектов. Это не код многократного использования.
Было бы намного лучше, если бы использование фабрики было примерно таким:
$connection = new PDO( .. blah.. );
$stmt = $connection->query( 'SELECT * FROM '.$type.' LIMIT '.$count );
$factory = new Factory;
$collection = $factory->buildCollection( $type, $stmt->fetchALL(PDO::FETCH_ASSOC) );
Конечно, с фабричным классом, который реализует это поведение.
Кроме того, вы можете посмотреть (при условии, что вы еще не видели) два видео на эту тему:
Я далек от авторитета по шаблону проектирования фабрики, но я обычно делегирую инстанцирование подклассу.
<?php
class AssetFactory
{
public static function Create($asset, $count)
{
$objects = false;
switch ( strtolower($asset) ) {
case 'item':
case 'job':
$class_name = 'Asset'.$asset;
$asset_obj = $class_name::getInstance();
$objects = $asset_obj->Create($count);
break;
default:
// Invalid asset
break;
}
return $objects;
}
}
class Asset
{
var $name = null;
var $table = null;
private static $instance = null;
private function __construct() {}
private function __clone() {}
public function Create($count)
{
$objects = array();
$db = new Database();
$rows = $db->query("SELECT * FROM ".$this->table." LIMIT ".$count);
if ( is_array($rows) ) {
foreach($rows as $row)
{
$objects[] = new Item($row);
}
}
return $objects;
}
public static function getInstance()
{
if ( empty($self::$instance) ) {
$class_name = __CLASS__;
self::$instance = new $class_name();
}
return self::$instance;
}
}
class AssetItem extends Asset
{
private function __construct()
{
$this->name = 'Item';
$this->table = 'item';
parent::__construct();
}
}
class AssetJob extends Asset
{
private function __construct()
{
$this->name = 'Job';
$this->table = 'job';
parent::__construct();
}
}