
Фабричный метод

В этой статье я кратко расскажу о таком порождающем паттерне проектирования как «фабричный метод», а также приведу пример того, где его можно использовать касательно игр.
Суть паттерна заключается в том, что мы можем в базовом классе предоставить некоторый интерфейс для создания неких абстрактных объектов, а в наследниках реализовать методы, создающие уже конкретные объекты.
Поясню на примере. Допустим, разрабатываем мы игру про войну. У нас есть базовый класс военной техники:
class Vehicle
{
// ...
}
Реальная же техника наследует этот класс и реализует какую-то свою функциональность. Пусть у нас в игре будет танк, джип и пушка:
class Tank extends Vehicle
{
// ...
}
class Jeep extends Vehicle
{
// ...
}
class Turret extends Vehicle
{
// ...
}
Вся эта техника умеет стрелять. Проблема в том, что стреляет она разными снарядами, которые хоть чем-то и похожи (умеют летать и попадать в цель), но ведут местами себя по-разному (например, пушечные ядра разрываются при попадании). Поэтому мы объявляем некоторый базовый класс снаряда, реализующий общую для всех функциональность:
class Weapon
{
public function fly(): void { /* ... */ }
}
а в наследниках уже будем определять его поведение для каждого типа снаряда:
class Cannonball extends Weapon
{
public override function fly(): void
{
super.fly();
if (/* попали в цель */)
bang(); // взорваться
}
// ...
}
class Bullet extends Weapon
{
// ...
}
Теперь давайте добавим в базовый класс техники возможность стрелять:
class Vehicle
{
public function fire(): Weapon { return null; }
}
а в классах-наследниках перегружаем метод, позволяя каждому типу техники стрелять соответствующими снарядами, на практике которые будут оказываться разными в зависимости от типа техники:
class Tank extends Vehicle
{
public override function fire(): Weapon { return new Cannonball(); }
}
class Jeep extends Vehicle
{
public override function fire(): Weapon { return new Bullet(); }
}
class Turret extends Vehicle
{
public override function fire(): Weapon { return new Cannonball(); }
}
Теперь мы можем работать с однотипной техникой, которая стреляет однотипными снарядами:
var vehicles: Array = [new Tank(), new Jeep(), new Turret()];
for each (var vehicle: Vehicle in vehicles)
{
var weapon: Weapon = vehicle.fire();
weapon.fly();
}
в том числе можем, например, воспользоваться этим в базовом классе:
class Vehicle
{
public function fire(): Weapon { return null; }
public function moveAndFire()
{
Weapon weapon = fire();
weapon.fly();
}
}
// ...
Vehicle vehicle = new Tank();
vehicle.moveAndFire(); // тут внутри будет вызван метод fly() для объекта класса Cannonball, созданного танком
- +11
- NightmareZ
Комментарии (21)
Советую как можно улучшить:
А) Ответь на главные вопросы:
1. Что такое фабричный метод, и почему метод.
2. Зачем он нужен.
3. Где он у тебя в примерах вообще. А то я сначала подумал что ты под ФМ решил про принципы ООП порассказать.
Б) Очисть статью от ненужного лишнего кода (ну или расположить его хотя-бы в правильном порядке).
В) Начать с теории и перейти к практике с пояснениями.
Вот тогда получится что-то вменяемое. Хотя вот уже 4 человекам очень понравилась твоя подача материала. Хотя я полагаю, если он не знали что такое ФМ, то и не узнали.
Зы: я уже молчу про некорректные названия классов (weapon-оружие, это автомат, пистолет и т.д, а не ядро, пуля, картечь и т.д.). Хотя получилось что не молчу ;D
2. Пример это демонстрирует.
3. Метод fire().
«И сам этот паттерн это ж для каких олдфажных кодеров на прримитивных языках придуман».
Совершенно очевидно, что из-за гениального примера вы не поняли, что такое фабричный метод :) Не в обиду сказано, я сам сначала не понял, что автор имел в виду пока не вчитался в код. ФМ — отличный паттерн, но лучше почитать про него в вики. И сразу про обычные фабрики, они вообще используются в каждом втором движке.
1. http://ru.wikipedia.org/wiki/Функтор_(программирование)
2. Я прекрастно понял и кривость изложения и сам паттерн и где он есть в статье и почему он показывает отсутствие мозгов при применении в АС3, где есть встроенный тип Class, реализующий отражения. А также функторы, которыми вопрос решается наподобие С/С++.
Я пожалуй попозже напишу как это все делается. Ели никто не сделает этого раньше.
поставил + за старания, ну и потому что минусовать нельзя…
Магистр йода ;D
Иначе как-то… Не буду придумывать — peregrimm хорошо сказал ;)
Не стоит писать про то, что не используете, но вчера услышали на лекции.
PS. Ни разу в жизни по работе за последние 6 лет не приходилось писать фабричные методы (разработка игр, не движков, не энтерпрайз-систем, просто игр). В отличие скажем от обычных фабрик. Вот пост про них был бы полезнее, судя по тому как люди (в том числе и с FGB) любят раскидать switch-case или if-else гарды по всему проекту.