Назад Вперед Зміст


Породжуючі патерни

(Джерело: https://javarush.ru/groups/posts/2370-pattern-proektirovanija-factory)

Породжуючі шаблони описують створення (instantiate) об'єкта або групи пов'язаних об'єктів.

Основні концепції

Спочатку створюються абстрактні класи. З їх допомогою легше виявити та задати потрібні типи, виразити типи як збірні поняття інших типів. Описуються інтерфейси взаємодії з кожним типом. Абстрактно (без реалізації) описуються процеси створення екземплярів цих типів та варіанти їх використання через наявні інтерфейси.

Після визначення типів, опису інтерфейсів та абстрагування процесів створення, можна приступити до вибору структур даних та алгоритмів для їх обробки, а також до реалізації конкретних класів.

Типи породжуючих патернів

  1. Проста фабрика (Simple Factory)
  2. Фабричний метод (Factory Method)
  3. Абстрактна фабрика (Abstract Factory)

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

Коли використовувати?

Коли створення об'єкта містить певну логіку, а не просто присвоєння значень, доцільно делегувати це завдання спеціалізованій фабриці.

Фабрика та Фабричний метод у C#

1. Проста Фабрика (Simple Factory)

Реалізація фабрики для створення різних типів качок:


using System;

// Проста фабрика для створення качок
public class DuckFactory
{
    public Duck CreateDuck(string type)
    {
        switch (type.ToLower())
        {
            case "mallard":
                return new MallardDuck();
            case "model":
                return new ModelDuck();
            case "rubber":
                return new RubberDuck();
            default:
                throw new ArgumentException($"Невідомий тип качки: {type}");
        }
    }
}

// Використання фабрики
class Program
{
    static void Main(string[] args)
    {
        DuckFactory factory = new DuckFactory();
        
        Duck mallard = factory.CreateDuck("mallard");
        Duck model = factory.CreateDuck("model");
        Duck rubber = factory.CreateDuck("rubber");
        
        Console.WriteLine("Створено качку: " + mallard.Display);
        Console.WriteLine("Створено качку: " + model.Display);
        Console.WriteLine("Створено качку: " + rubber.Display);
    }
}
    

2. Фабричний метод (Factory Method)

Розширена система з регіональними варіантами качок:


// Абстрактний клас з фабричним методом
public abstract class DuckCreator
{
    // Фабричний метод
    public abstract Duck CreateDuck();
    
    public void DisplayDuckInfo()
    {
        Duck duck = CreateDuck();
        Console.WriteLine($"Створено качку: {duck.Display}");
        Console.WriteLine($"Звук: {duck.PerformQuack()}");
        Console.WriteLine($"Політ: {duck.PerformFly()}");
    }
}

// Конкретні фабрики для різних типів качок
public class MallardDuckCreator : DuckCreator
{
    public override Duck CreateDuck() => new MallardDuck();
}

public class ModelDuckCreator : DuckCreator
{
    public override Duck CreateDuck() => new ModelDuck();
}

public class RubberDuckCreator : DuckCreator
{
    public override Duck CreateDuck() => new RubberDuck();
}

// Використання фабричного методу
class Program
{
    static void Main(string[] args)
    {
        DuckCreator[] creators = {
            new MallardDuckCreator(),
            new ModelDuckCreator(),
            new RubberDuckCreator()
        };
        
        foreach (var creator in creators)
        {
            creator.DisplayDuckInfo();
            Console.WriteLine();
        }
    }
}
   

Порівняння патернів

Критерій Проста Фабрика Фабричний метод
Інкапсуляція Весь код в одному методі Розподілений по підкласах
Розширюваність Потрібно змінювати фабрику Додаємо нові підкласи
Складність Простіша реалізація Складніша структура
Використання Коли об'єктів небагато і рідко змінюються Коли система повинна бути розширюваною
Принцип SOLID Може порушувати OCP Дотримується OCP

Висновок:

Просту фабрику варто використовувати для простих випадків, коли кількість типів об'єктів невелика і рідко змінюється. Фабричний метод краще підходить для складних систем, де потрібна гнучкість і розширюваність.

Приклад з кофейнею

Створимо систему для автоматизації роботи кав'ярні:

  1. Базовий клас Coffee та його похідні (Americano, Cappuccino, Espresso, Latte)
  2. Enum для типів кави
  3. Фабрика для створення конкретних видів кави

Код реалізації

public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}

public class CoffeeFactory {
    public Coffee createCoffee(CoffeeType type) {
        switch(type) {
            case ESPRESSO: return new Espresso();
            case AMERICANO: return new Americano();
            case CAFFE_LATTE: return new CaffeLatte();
            case CAPPUCCINO: return new Cappuccino();
            default: throw new IllegalArgumentException("Unknown coffee type");
        }
    }
}

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

Розширимо наш приклад для підтримки різних стилів кав'ярень (італійський, американський).

Структура

  1. Абстрактний клас CoffeeShop з фабричним методом createCoffee()
  2. Конкретні реалізації для різних стилів (ItalianCoffeeShop, AmericanCoffeeShop)
  3. Різні варіанти продуктів для кожного стилю

Код реалізації

public abstract class CoffeeShop {
    public abstract Coffee createCoffee(CoffeeType type);
    
    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = createCoffee(type);
        coffee.grindCoffee();
        coffee.makeCoffee();
        coffee.pourIntoCup();
        return coffee;
    }
}

public class ItalianCoffeeShop extends CoffeeShop {
    @Override
    public Coffee createCoffee(CoffeeType type) {
        switch(type) {
            case ESPRESSO: return new ItalianEspresso();
            // інші типи...
        }
    }
}

Переваги


Назад Вперед Зміст