Autumn SALE
Metoda wytwórcza

Metoda wytwórcza w języku Java

Metoda wytwórcza jest kreacyjnym wzorcem projektowym rozwiązującym problem tworzenia obiektów-produktów bez określania ich konkretnych klas.

Metoda wytwórcza definiuje metodę która ma służyć tworzeniu obiektów bez bezpośredniego wywoływania konstruktora (poprzez operator new). Podklasy mogą nadpisać tę metodę w celu zmiany klasy tworzonych obiektów.

Jeśli masz problem ze zrozumieniem różnicy pomiędzy poszczególnymi koncepcjami i wzorcami wytwórczymi, przeczytaj nasze Porównanie fabryk.

Złożoność:

Popularność:

Przykłady użycia: Wzorzec Metoda wytwórcza jest szeroko rozpowszechniony w kodzie Java. Przydaje się gdy trzeba wyposażyć kod w wysoki poziom elastyczności.

Wzorzec jest obecny w głównych bibliotekach Java:

Identyfikacja: Metody wytwórcze można rozpoznać po metodach kreacyjnych tworzących obiekty na podstawie konkretnych klas, ale zwracających typ abstrakcyjny lub interfejs.

Tworzenie międzyplatformowych elementów graficznego interfejsu użytkownika (GUI)

W poniższym przykładzie przyciski odgrywają rolę produktów, a okna dialogowe — twórców.

Różne rodzaje okien dialogowych wymagają własnych typów elementów. Dlatego na każde okno dialogowe tworzymy podklasę i nadpisujemy jej metody wytwórcze.

W rezultacie każdy rodzaj okna dialogowego stworzy instancje odpowiednich klas przycisków. Klasa bazowa okna dialogowego współdziała z produktami za pośrednictwem ich wspólnego interfejsu, więc jej kod będzie działał nawet po wszystkich zmianach.

buttons

buttons/Button.java: Wspólny interfejs produktu

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

buttons/HtmlButton.java: Konkretny produkt

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: Kolejny konkretny produkt

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: Bazowy twórca

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: Konkretny twórca

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: Kolejny konkretny twórca

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: Kod klienta

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: Wyniki działania (HtmlDialog)

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

OutputDemo.png: Wyniki działania (WindowsDialog)

Metoda wytwórcza w innych językach

Metoda wytwórcza w języku C# Metoda wytwórcza w języku C++ Metoda wytwórcza w języku Go Metoda wytwórcza w języku PHP Metoda wytwórcza w języku Python Metoda wytwórcza w języku Ruby Metoda wytwórcza w języku Rust Metoda wytwórcza w języku Swift Metoda wytwórcza w języku TypeScript