«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Простая фабрика

Простая фабрика

Опубликовано 17 ноября 2024 г.
Просматривать:281

Что такое простая фабрика?

Простая фабрика не является шаблоном проектирования. Он просто отделяет создание объекта от клиентского кода. Другими словами, фабрика Simple инкапсулирует создание экземпляров объекта, перемещая логику создания экземпляров в отдельный класс.

Простую фабрику часто путают с шаблоном Factory. Мы собираемся изучить Simple Factory, чтобы выяснить их разницу. Кроме того, изучение Simple Factory помогает нам легко понять шаблон Factory.

Какую проблему может решить Simple 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().

Simple Factory

  1. Клиент
    Клиент создает экземпляр конкретного объекта гамбургера через SimpleBurgerFactory. Обратите внимание, что с точки зрения клиента мы не знаем, какой конкретный бургер будет создан, то есть логика создания объекта теперь отделена от клиента.

  2. SimpleBurgerFactory
    Этот класс инкапсулирует то, что меняется, а именно, в данном случае, логику создания объекта! createBurger() объявлен как статический метод, потому что клиент хочет использовать этот класс для создания экземпляра объекта (конечно, мы не можем иметь экземпляр до его создания!). createBurger() принимает перечисление BurgerType, чтобы определить, какой тип бургера следует создать.

  3. Бургер
    Этот абстрактный класс обеспечивает общий интерфейс для всех гамбургеров и определяет поведение по умолчанию.

  4. Подклассы бургеров
    Вот наши бетонные изделия. Они могут реализовать определенное поведение, переопределяя методы, если они расширяют класс Burger.

Структура

Simple Factory

Код

public enum BurgerType {
    BEEF,
    CHICKEN,
    FISH,
    VEGGIE
}
// Abstract Product
public abstract class Burger {

    public BurgerType burgerType;
    public List toppings = 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;
        List items = List.of("lettuce", "pickle slices", "tomato slice", "BBQ sauce");
        toppings.addAll(items);
    }
}
// Concrete product
public class VeggieBurger extends Burger {

    public VeggieBurger() {
        burgerType = BurgerType.VEGGIE;
        List items = 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

Подводные камни

  • Код принятия решений для создания экземпляров объектов иногда может оказаться более сложным. В таком случае мы могли бы также рассмотреть возможность использования метода Factory.

Сравнение с заводским шаблоном

  • В простой фабрике обычно существует один класс фабрики, который решает, какой тип продукта создавать, а в шаблоне «Фабрика» может быть несколько фабрик.
  • Простая фабрика часто использует статический метод для создания объектов, что упрощает вызов, но затрудняет расширение. С другой стороны, фабричный метод использует абстрактный метод в суперклассе, который действует как интерфейс для всех фабрик и подклассов и обеспечивает конкретную реализацию для создания экземпляров объекта.

Здесь вы можете проверить все реализации шаблонов проектирования.
Репозиторий GitHub


P.S.
Я новичок в ведении технического блога, если у вас есть совет по улучшению моего письма или есть какие-либо непонятные моменты, оставьте комментарий!
Спасибо, что читаете :)

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/sota_333ad4b72095606ab40c/simple-factory-3bnl?1. Если есть какие-либо нарушения, свяжитесь с [email protected], чтобы удалить их.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3