SOLDES de printemps
Fabrique

Fabrique en Java

La Fabrique est un patron de conception de création qui permet de créer des produits sans avoir à préciser leurs classes concrètes.

La fabrique définit une méthode qui doit être utilisée pour créer des objets à la place de l’appel au constructeur (opérateur new). Les sous-classes peuvent redéfinir cette méthode pour modifier la classe des objets qui seront créés.

Lisez notre Comparaison des fabriques si vous avez du mal à saisir la différence entre les divers concepts et patrons.

Complexité :

Popularité :

Exemples d’utilisation : La fabrique est très largement utilisée en Java. Elle va permettre de rendre votre code très flexible.

Ce patron est présent dans les bibliothèques principales de Java :

Identification : La fabrique peut être reconnue grâce à ses méthodes de création qui produisent des objets depuis les classes concrètes, mais les retournent en tant qu’objets de type abstrait ou d’interface.

Fabrication d’éléments d’une GUI multiplateforme

Dans cet exemple, les boutons jouent le rôle du produit et les boîtes de dialogue sont les créateurs.

Les différentes boîtes de dialogues ont besoin de leurs propres types d’éléments. C’est pour cela que nous créons une sous-classe pour chaque boîte de dialogue et redéfinissons leur fabrique.

À présent, chaque boîte de dialogue instanciera ses propres classes de boutons. La boîte de dialogue de base utilise une interface commune pour manipuler les produits, ainsi son code fonctionne toujours même après toutes ces modifications.

buttons

buttons/Button.java: Interface commune des produits

package refactoring_guru.factory_method.example.buttons;

/**
 * Common interface for all buttons.
 */
public interface Button {
    void render();
    void onClick();
}

buttons/HtmlButton.java: Produit concret

package refactoring_guru.factory_method.example.buttons;

/**
 * HTML button implementation.
 */
public class HtmlButton implements Button {

    public void render() {
        System.out.println("<button>Test Button</button>");
        onClick();
    }

    public void onClick() {
        System.out.println("Click! Button says - 'Hello World!'");
    }
}

buttons/WindowsButton.java: Produit concret supplémentaire

package refactoring_guru.factory_method.example.buttons;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * Windows button implementation.
 */
public class WindowsButton implements Button {
    JPanel panel = new JPanel();
    JFrame frame = new JFrame();
    JButton button;

    public void render() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label = new JLabel("Hello World!");
        label.setOpaque(true);
        label.setBackground(new Color(235, 233, 126));
        label.setFont(new Font("Dialog", Font.BOLD, 44));
        label.setHorizontalAlignment(SwingConstants.CENTER);
        panel.setLayout(new FlowLayout(FlowLayout.CENTER));
        frame.getContentPane().add(panel);
        panel.add(label);
        onClick();
        panel.add(button);

        frame.setSize(320, 200);
        frame.setVisible(true);
        onClick();
    }

    public void onClick() {
        button = new JButton("Exit");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                frame.setVisible(false);
                System.exit(0);
            }
        });
    }
}

factory

factory/Dialog.java: Créateur de base

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;

/**
 * Base factory class. Note that "factory" is merely a role for the class. It
 * should have some core business logic which needs different products to be
 * created.
 */
public abstract class Dialog {

    public void renderWindow() {
        // ... other code ...

        Button okButton = createButton();
        okButton.render();
    }

    /**
     * Subclasses will override this method in order to create specific button
     * objects.
     */
    public abstract Button createButton();
}

factory/HtmlDialog.java: Créateur concret

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;
import refactoring_guru.factory_method.example.buttons.HtmlButton;

/**
 * HTML Dialog will produce HTML buttons.
 */
public class HtmlDialog extends Dialog {

    @Override
    public Button createButton() {
        return new HtmlButton();
    }
}

factory/WindowsDialog.java: Créateur concret supplémentaire

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;
import refactoring_guru.factory_method.example.buttons.WindowsButton;

/**
 * Windows Dialog will produce Windows buttons.
 */
public class WindowsDialog extends Dialog {

    @Override
    public Button createButton() {
        return new WindowsButton();
    }
}

Demo.java: Code client

package refactoring_guru.factory_method.example;

import refactoring_guru.factory_method.example.factory.Dialog;
import refactoring_guru.factory_method.example.factory.HtmlDialog;
import refactoring_guru.factory_method.example.factory.WindowsDialog;

/**
 * Demo class. Everything comes together here.
 */
public class Demo {
    private static Dialog dialog;

    public static void main(String[] args) {
        configure();
        runBusinessLogic();
    }

    /**
     * The concrete factory is usually chosen depending on configuration or
     * environment options.
     */
    static void configure() {
        if (System.getProperty("os.name").equals("Windows 10")) {
            dialog = new WindowsDialog();
        } else {
            dialog = new HtmlDialog();
        }
    }

    /**
     * All of the client code should work with factories and products through
     * abstract interfaces. This way it does not care which factory it works
     * with and what kind of product it returns.
     */
    static void runBusinessLogic() {
        dialog.renderWindow();
    }
}

OutputDemo.txt: Résultat de l’exécution (HtmlDialog)

<button>Test Button</button>
Click! Button says - 'Hello World!'

OutputDemo.png: Résultat de l’exécution (WindowsDialog)

Fabrique dans les autres langues

Fabrique en C# Fabrique en C++ Fabrique en Go Fabrique en PHP Fabrique en Python Fabrique en Ruby Fabrique en Rust Fabrique en Swift Fabrique en TypeScript