Это правильный шаблон фабричный метод?


Я знаю, что есть много подобных вопросов, но я не понимаю большинство из этих вопросов, потому что я не уверен, если я знаю, что такое шаблон метода фабрики.

Итак, прочитав много примеров в Интернете, я придумал следующие простые классы.

Я делаю это правильно? Если так...никаких улучшений я могу добавить?

abstract class Driveable
{
    abstract public function start();
    abstract public function stop();

}

class CoupeDriveable extends Driveable
{
    public function start()
    {
    }

    public function stop()
    {
    }
}

class MotorcycleDriveable extends Driveable
{
    public function start()
    {
    }

    public function stop()
    {
    }   
}

class SedanDriveable extends Driveable
{
    public function start()
    {
    }

    public function stop()
    {
    }   
}

class DriveableFactory
{
    static public function create($numberOfPeople){

        if( $numberOfPeople == 1 )
        {
            return new MotorcycleDriveable;
        }       
        elseif( $numberOfPeople == 2 )
        {
            return new CoupleDriveable;
        }
        elseif( $numberOfPeople >= 3 && $numberOfPeople < 4)
        {
            return SedanDriveable;
        }
    }
}


class App
{
    static public function getDriveableMachine($numberOfPeople)
    {
        return DriveableFactory::create($numberOfPeople);
    }
}


$DriveableMachine = App::getDriveableMachine(2);
$DriveableMachine->start();

Обновление: по данным palacsint и Сергей по окрестностя советы, я обновил мой код.

abstract class DriveableFactory
{
    static public function create($numberOfPeople);
}

class CarDriveableFactory extends DriveableFactory
{
    static public function create($numberOfPeople){

        $products = array
        (
            1=>"MotorcycleDriveable",
            2=>"CoupeDriveable",
            3=>"SedanDriveable",
            4=>"SedanDriveable"
        );

        if( isset( $products[$numberOfPeople] ) )
        {
            return new $products[$numberOfPeople];
        }
        else
        {
            throw new Exception("unable to find a suitable drivable car");
        }


    }
}


730
10
задан 2 ноября 2011 в 07:11 Источник Поделиться
Комментарии
3 ответа


Суть паттерна фабричный метод, чтобы "определить интерфейс
для создания объекта, но давайте подклассы решить, какой класс
инстанцировать. Фабричный метод позволяет классу отложить инстанцирование в
подклассы".

Если вы настаиваете на выше Гоф определения есть две проблемы.

Во-первых, вы должны создать DriveableFactory интерфейс и переименовать DriveableFactory (например) CarDriveableFactory.

abstract class DriveableFactory
{
static public function create($numberOfPeople);
}

class CarDriveableFactory extends DriveableFactory
{
static public function create($numberOfPeople) { ... }
}

Но ваш код-это нормально, если вам не нужно (нет причин) реферат DriveableFactory интерфейс не добавить его в код.

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

Наконец, приложение класса выглядит ненужным. Итак, я напишу что-то вроде этого:

DriveableFactory factory = new CarDriveableFactory();
$DriveableMachine = factory->getDriveableMachine(2);
$DriveableMachine->start();

Небольшие улучшения:

3.5 - это допустимое значение? И 3.1415? Если не учитывать изменение

else if( $numberOfPeople >= 3 && $numberOfPeople < 4)

для

else if($numberOfPeople == 3 || $numberOfPeople == 4)

В последней строке создать() метод, который я бы бросить IllegalArgumentException (или аналог в PHP) с сообщением "недопустимое значение:" . $numberOfPeople.

7
ответ дан 2 ноября 2011 в 11:11 Источник Поделиться

Я думаю, что это хорошая реализация, но можно уменьшить несколько, если остальные условия
Я не знаю, в PHP я могу написать тебе, как я реализую в коде C#
в C# существует особый тип словарей, которые представляют значение ключа пары коллекцию и если в PHP существует несколько подобных Вы можете использовать его взглянуть на foolwing код

    private Driveable Create(int numberOfPeople)
{
Dictionary<int, Driveable> registerDriveable = new Dictionary<int, Driveable>();
registerDriveable.Add(1, new MotorcycleDriveable());
registerDriveable.Add(2, new CoupeDriveable());
registerDriveable.Add(3, new SedanDriveable());
registerDriveable.Add(4, new SedanDriveable());
// and then find in dictionary by key

//this code return the new CoupeDriveable()
Driveable driveable = registerDriveable[numberOfPeople];
return driveable;
}

преимуществом этого решения является, когда вы будете добавлять пыльников типа Сплавная вам не нужно добавлять дополнительные если еще
только одна линия

registerDriveable.Add(10, new BusDriveable());

4
ответ дан 2 ноября 2011 в 10:11 Источник Поделиться

Как Симан отметил в комментарии, это пример шаблона "фабрика"--не фабричный метод шаблон. На самом деле, вы, как правило, подкласс завода, чтобы определить класс для создания экземпляра, а не приняли это решение в зависимости от параметра. Возможно, этот пример сочетает в строителя шаблон или другая, чье имя я забыл на данный момент.

Шаблона "фабрика" определяет интерфейс для создания тех случаях, когда конкретные реализации определяют как создать тех случаях, и какие зависимости они требуют. Интерфейсы используются здесь, потому что фабрики создать метод вызывается другими классами.

В то время как связанные, метод фабрики шаблон отличается тем, что абстрактный класс определяет защищенную создать метод, который вызывается конкретные подклассы--не внешне. Вы всегда можете заменить метод на основе шаблона с внешнего фабрики, чтобы увеличить гибкость.

Вот простой пример использования шаблона фабричный метод:

Абстрактная Фабрика

abstract class Race
{
private $racers = array();

public function __construct($numRacers) {
for ($i = 0; $i < $numRacers; $i++) {
$this->racers[] = $this->createRacer($i);
}
}

protected abstract function createRacer($racerNum);

public function startRace() { ... use $this->racers ... }
}

Конкретные Реализации Фабрики

class MotorcycleRace extends Race
{
protected function createRacer($racerNum) {
return new MotorcycleRacer($racerNum);
}
}

class DragsterRace extends Race
{
protected function createRacer($racerNum) {
return new DragsterRacer($racerNum);
}
}

class FormulaOneRace extends Race
{
protected function createRacer($racerNum) {
return new FormulaOneRacer($racerNum);
}
}

0
ответ дан 14 марта 2013 в 05:03 Источник Поделиться

Другие вопросы по теме
Как упростить мой доступ к данным или переложить его в ОРМ
1 ноября 2011 в 08:11
ПДО (MySQL), то подключение и класс запроса, безопасности и логики
31 октября 2011 в 06:10