January
В предыдущей статье по проектированию был описан паттерн Factory Method. Как и было обещано, на этот раз мы рассмотрим шаблон проектирования под названием Abstract Factory.
Абстрактная фабрика предоставляет интерфейс для создания целых семейств объектов без указания конкретных классов. Объекты каждого семейства должны быть логически связаны между собой.
Перед тем, как привести пример использования Фабрики на Java, рассмотрим небольшую диаграмму классов (с Paint я творю чудеса :)):

Из диаграммы видно, что клент после ипользования Фабрики для создания объектов, манипулирует объектами на более высоком уровне абстракции.
Предположим, мы создаем компьютерную игрушку. Игрок будет управлять некоторым отрядом: маг, воин, лучник. Раса отряда не является ключевым моментом, поэтому можно использовать абстрактную фабрику:
public abstract class SquadronFactory {
public abstract Mage createMage() {}
public abstract Archer createArcher() {}
public abstract Warrior createWarrior() {}
}
Интерфейсы персонажей будут следующие:
public interface Mage {
public void cast();
}
public interface Archer {
public void shoot();
}
public interface Warrior {
public void attack();
}
Перейдем к конкретным классам:
public class ElfSquadronFactory extends SquadronFactory {
public Mage createMage() {
return new ElfMage();
}
public Archer createArcher() {
return new ElfArcher();
}
public Warrior createWarrior() {
return new ElfWarrior();
}
}
public class ElfMage implements Mage {
public void cast() {
// использовать магию эльфов
}
}
public class ElfArcher implements Archer {
public void shoot() {
// использовать лук эльфов
}
}
public class ElfWarrior implements Warrior {
public void attack() {
// использовать меч эльфов
}
}
Аналогичные классы можно создать для других рас.
Ну а теперь перейдем к использованию выше описанных классов для создания отряда. Функция создания отрядов будет иметь следующий вид:
public void createSquadron (SquadronFactory factory) {
Mage mage = factory.createMage();
Archer archer = factory.createArcher();
Warrior warrior = factory.createWarrior();
...
}
В данный метод в качестве параметра передается конкретная фабрика. В результате мы получаем семейство классов, которые будут вести себя четко определенным образом.
Хочу обратить ваше внимание на то, что абстрактная фабрика может быть не только абстрактным классом, но и интерфейсом, и конкретным классом. Конкретные фабрики чаще всего реализуют паттерн Singleton.
Используйте паттерн Абстрактная Фабрика в таких случаях:
- система не должна зависеть от способа создания объектов;
- система работает с одним из нескольких семейств объектов;
- объекты внутри семейства взаимосвязаны.
Комментарии по поводу статьи приветствуются.
5 Comments »
RSS feed for comments on this post. TrackBack URI
было бы понятнее если бы uml схема отражала суть примера ![]()
Было бы хорошо, если бы автор попутно проводил сравнения с похожими паттернами- обьяснял различия, преимущества. Например в данном случае AbstractFacory и FactoryMethod.
Ребята, спасибо за комментарии.
В ближайшее время грядет refactoring сайта. Будут исправлены все ошибки и неточности с высоты приобретенного опыта. Статьи будут дополнены новой информацией. Большинство ваших предложений (в идеале - все) будут не только приняты к сведению, но и реализованы.
Здравствуйте!
Хотелось бы задать глупый вопрос вам, так как я новичок.
Для чего вообще нужно создавать абстрактный класс фабрики и интерфейсы для война, мага и т.д.
Можно же просто создать классы фабрики и эти войнов, магов.
И ещё, а в чем принципиальное отличие между фабрикой и фабричным методом?
Заранее благодарен, за помощь! =)
Я лично использую factory для следующей ситуации.
Есть базовая коллекция объектов, инкапсулирующих таблицу из бд. Ну и есть группа унаследованных коллекций для разного вида таблиц.
С какой бд они будут работать в определенный момент времени - неизвестно. И зависит это от многих факторов. Но в конечном счете всё, что необходимо - это актуальный на данный момент connection string. Так вот, вся логика, связанная с созданием этих коллекций, включая генерацию connection string’а и прочие предварительные заморочки, выносятся в отдельный класс.
Есть и другие подобные примеры. Многие программисты используют подобные решения для разных задач. И чтобы каждый раз не объяснять друг другу то, что я тут рассказываю, они придумали этому решению название “Factory”.