Простая фабрика не является шаблоном проектирования. Он просто отделяет создание объекта от клиентского кода. Другими словами, фабрика Simple инкапсулирует создание экземпляров объекта, перемещая логику создания экземпляров в отдельный класс.
Простую фабрику часто путают с шаблоном Factory. Мы собираемся изучить Simple Factory, чтобы выяснить их разницу. Кроме того, изучение Simple Factory помогает нам легко понять шаблон Factory.
Следует избегать программирования для конкретной реализации, поскольку это затрудняет поддержку приложения. Всегда предпочтительнее программировать интерфейс. Если вы создаете экземпляр конкретного класса в клиентском коде, то Simple Factory пригодится, поскольку Simple Factory может отделить создание объекта от клиента. Это делает наше приложение более расширяемым и удобным в обслуживании.
Разрабатываем систему для бургерной. Системе необходимо создавать различные гамбургеры, такие как бургер с говядиной, бургер с курицей и т. д.
Наша первая попытка будет такой:
// Client orders a burger Burger orderBurger(String type) { Burger burger; if (type.equals("beef")) { burger = new BeefBurger(); } else if (type.equals("chicken")) { burger = new ChickenBurger(); } else if (type.equals("fish")) { burger = new FishBurger(); } burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; }
Проблема в том, что мы пишем код для реализации, а не для интерфейса. Где? Мы используем оператор if и создаем экземпляр конкретного класса на основе типа бургера.
Почему это проблема? Наш клиентский код тесно связан с созданием объектов, что приводит к меньшей гибкости! Допустим, мы больше не будем продавать рыбные бургеры, а начнем продавать вегетарианские бургеры. Нам нужно посетить наш клиентский код и изменить его. То есть он не закрыт для модификации.
Чтобы решить проблему, мы можем создать отдельный класс, который будет отвечать только за создание объектов. Тогда нашему клиентскому коду не нужно будет беспокоиться о создании объекта и он сможет зависеть от абстракции. Эта техника известна как «Инкапсуляция того, что меняется» . Мы ожидаем, что код создания экземпляров конкретных объектов будет часто меняться, в то время как процессы «prereBun()», «GrillPatty()», «addToppings()», «wrap()», вероятно, останутся одинаковыми для всех бургеров в будущем.
Преимущество простой фабрики в том, что ее можно повторно использовать другими классами. У нас могут быть другие клиентские классы, такие как BurgerRestaurant, BurgerCateringShop, которые будут использовать метод SimpleBurgerFactory.createBurger().
Клиент
Клиент создает экземпляр конкретного объекта гамбургера через SimpleBurgerFactory. Обратите внимание, что с точки зрения клиента мы не знаем, какой конкретный бургер будет создан, то есть логика создания объекта теперь отделена от клиента.
SimpleBurgerFactory
Этот класс инкапсулирует то, что меняется, а именно, в данном случае, логику создания объекта! createBurger() объявлен как статический метод, потому что клиент хочет использовать этот класс для создания экземпляра объекта (конечно, мы не можем иметь экземпляр до его создания!). createBurger() принимает перечисление BurgerType, чтобы определить, какой тип бургера следует создать.
Бургер
Этот абстрактный класс обеспечивает общий интерфейс для всех гамбургеров и определяет поведение по умолчанию.
Подклассы бургеров
Вот наши бетонные изделия. Они могут реализовать определенное поведение, переопределяя методы, если они расширяют класс Burger.
public enum BurgerType { BEEF, CHICKEN, FISH, VEGGIE }
// Abstract Product public abstract class Burger { public BurgerType burgerType; public Listtoppings = new ArrayList(); public void prepareBun() { System.out.println("Preparing a bun"); } public void grillPatty() { if (burgerType == null) { throw new IllegalStateException("pattyType is undefined"); } System.out.println("Grill a " burgerType " patty"); } public void addToppings() { for (String item : toppings) { System.out.println("Add " item); } } public void wrap() { System.out.println("Wrap a burger up"); } }
// Concrete product public class BeefBurger extends Burger { public BeefBurger() { burgerType = BurgerType.BEEF; Listitems = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce"); toppings.addAll(items); } }
// Concrete product public class VeggieBurger extends Burger { public VeggieBurger() { burgerType = BurgerType.VEGGIE; Listitems = List.of("smoked paprika", "garlic chips", "crushed walnuts", "veggie sauce"); toppings.addAll(items); } // Concrete product can implement specific behavior that differs from other products @Override public void wrap() { System.out.println("Wrapping paper shouldn't print any meats but vegetables"); } }
// Simple factory, responsible for instantiating an object public class SimpleBurgerFactory { public static Burger createBurger(BurgerType type) { return switch (type) { case BEEF -> new BeefBurger(); case CHICKEN -> new ChickenBurger(); case FISH -> new FishBurger(); case VEGGIE -> new VeggieBurger(); default -> throw new IllegalArgumentException("unknown burger type"); }; } }
public class Client { public static void main(String[] args) { Burger burger = orderBurger(BurgerType.VEGGIE); System.out.println(burger); // Check if the object is actually veggie burger } public static Burger orderBurger(BurgerType type) { // Factory is responsible for object creation Burger burger = SimpleBurgerFactory.createBurger(type); burger.prepareBun(); burger.grillPatty(); burger.addToppings(); burger.wrap(); return burger; } }
Выход:
Preparing a bun Grill a VEGGIE patty Add smoked paprika Add garlic chips Add crushed walnuts Add veggie sauce Wrapping paper shouldn't print any meats but vegetables com.factories.simpleFactory.VeggieBurger@9807454
Здесь вы можете проверить все реализации шаблонов проектирования.
Репозиторий GitHub
P.S.
Я новичок в ведении технического блога, если у вас есть совет по улучшению моего письма или есть какие-либо непонятные моменты, оставьте комментарий!
Спасибо, что читаете :)
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3