JavaRush /Java Blog /Random-ID /Pola Desain: Pabrik Abstrak

Pola Desain: Pabrik Abstrak

Dipublikasikan di grup Random-ID
Halo! Hari ini kita akan terus mempelajari pola desain dan membicarakan tentang pabrik abstrak . Pola Desain: AbstrakPabrik - 1Apa yang akan kita lakukan selama perkuliahan:
  • Mari kita bahas apa itu pabrik abstrak dan masalah apa yang dipecahkan oleh pola ini;
  • kami akan membuat kerangka aplikasi lintas platform untuk memesan kopi dengan antarmuka pengguna;
  • Mari pelajari petunjuk penggunaan pola ini dengan diagram dan kode;
  • Sebagai bonus, ada telur Paskah yang tersembunyi di dalam kuliah, berkat itu Anda akan belajar menentukan nama sistem operasi menggunakan Java dan, tergantung pada hasilnya, melakukan tindakan tertentu.
Untuk memahami sepenuhnya pola ini, Anda perlu memiliki pemahaman yang baik tentang topik-topik berikut:
  • warisan di Jawa;
  • kelas dan metode abstrak di Java.

Masalah apa yang dipecahkan oleh pola pabrik abstrak?

Pabrik abstrak, seperti semua pola pabrik, membantu kita mengatur pembuatan objek baru dengan benar. Dengan bantuannya, kami mengelola “pelepasan” berbagai kelompok objek yang saling berhubungan. Berbagai kelompok objek yang saling terkait...Apa itu? Jangan khawatir: dalam praktiknya, semuanya lebih sederhana daripada yang terlihat. Mari kita mulai dengan apa yang mungkin merupakan kumpulan objek terkait? Misalkan Anda dan saya sedang mengembangkan strategi, dan ada beberapa unit tempur di dalamnya:
  • infanteri;
  • kavaleri;
  • pemanah.
Jenis unit tempur ini saling terkait satu sama lain, karena mereka bertugas dalam satu pasukan. Kita dapat mengatakan bahwa kategori-kategori yang tercantum di atas adalah sekumpulan objek yang saling terkait. Itu sudah beres. Namun pola pabrik abstrak digunakan untuk mengatur kreasi yang beragam kelompok objek yang saling berhubungan. Tidak ada yang rumit juga di sini. Mari kita lanjutkan contohnya dengan strategi. Mereka biasanya memiliki beberapa sisi berlawanan yang berbeda. Unit tempur pihak yang berbeda mungkin berbeda secara signifikan dalam penampilan. Prajurit berjalan kaki, penunggang kuda, dan pemanah tentara Romawi tidak sama dengan prajurit berjalan kaki, penunggang kuda, dan pemanah bangsa Viking. Dalam kerangka strategi, prajurit dari pasukan yang berbeda adalah kelompok objek berbeda yang saling berhubungan. Akan lucu jika, karena kesalahan seorang programmer, seorang prajurit berseragam Prancis dari zaman Napoleon, dengan senapan siap, berjalan-jalan di antara infanteri Romawi. Untuk mengatasi masalah seperti itulah diperlukan pola desain pabrik yang abstrak. Bukan, bukan masalah rasa malu dalam perjalanan waktu, tapi penciptaan berbagai kelompok objek yang saling berhubungan. Pabrik abstrak menyediakan antarmuka untuk membuat semua produk yang ada (objek keluarga). Pabrik abstrak biasanya memiliki banyak implementasi. Masing-masing dari mereka bertanggung jawab untuk menciptakan produk dari salah satu variasi. Sebagai bagian dari strategi, kami akan memiliki pabrik abstrak yang menciptakan infanteri abstrak, pemanah, dan kavaleri, serta implementasi dari pabrik ini. Sebuah pabrik yang menciptakan legiuner Romawi dan, misalnya, sebuah pabrik yang menciptakan prajurit Kartago. Abstraksi adalah prinsip terpenting dari pola ini. Klien pabrik bekerja dengannya dan dengan produk hanya melalui antarmuka abstrak. Oleh karena itu, kita tidak perlu memikirkan pejuang seperti apa yang saat ini kita ciptakan, tetapi alihkan tanggung jawab ini ke implementasi spesifik dari pabrik abstrak.

Kami terus mengotomatiskan kedai kopi

Pada kuliah terakhir kita mempelajari pola metode pabrik yang dengannya kita dapat memperluas bisnis kopi dan membuka beberapa titik penjualan kopi baru. Hari ini kami akan melanjutkan pekerjaan kami untuk memodernisasi bisnis kami. Dengan menggunakan pola pabrik abstrak, kami akan meletakkan dasar bagi aplikasi desktop baru untuk memesan kopi secara online. Saat kita menulis aplikasi untuk desktop, kita harus selalu memikirkan tentang lintas platform. Aplikasi kita harus bekerja pada macOS dan Windows (spoiler: Linux akan diserahkan kepada Anda sebagai pekerjaan rumah). Seperti apa tampilan aplikasi kita? Cukup sederhana: ini akan menjadi formulir yang terdiri dari kolom teks, kolom pilih, dan tombol. Jika Anda memiliki pengalaman menggunakan sistem operasi yang berbeda, Anda pasti memperhatikan bahwa di Windows tombol-tombolnya ditampilkan secara berbeda dibandingkan di Mac. Seperti yang lainnya... Jadi, mari kita mulai. Dalam peran rangkaian produk, seperti yang mungkin sudah Anda pahami, kami akan memiliki elemen antarmuka grafis:
  • tombol;
  • bidang teks;
  • bidang untuk seleksi.
Penafian. Dalam setiap antarmuka kita dapat mendefinisikan metode seperti onClick, onValueChangedatau onInputChanged. Itu. metode yang memungkinkan kita menangani berbagai peristiwa (mengklik tombol, memasukkan teks, memilih nilai dalam kotak pilih). Semua ini sengaja dihilangkan agar tidak membebani contoh dan membuatnya lebih visual untuk mempelajari pola pabrik. Mari kita definisikan antarmuka abstrak untuk produk kita:
public interface Button {}
public interface Select {}
public interface TextField {}
Untuk setiap sistem operasi, kita harus membuat elemen antarmuka sesuai gaya sistem operasi tersebut. Kami menulis untuk Windows dan MacOS. Mari buat implementasi untuk Windows:
public class WindowsButton implements Button {
}

public class WindowsSelect implements Select {
}

public class WindowsTextField implements TextField {
}
Sekarang hal yang sama untuk MacOS:
public class MacButton implements Button {
}

public class MacSelect implements Select {
}

public class MacTextField implements TextField {
}
Besar. Sekarang kita dapat memulai pabrik abstrak kita, yang akan membuat semua tipe produk abstrak yang ada:
public interface GUIFactory {

    Button createButton();
    TextField createTextField();
    Select createSelect();

}
Sempurna. Seperti yang Anda lihat, sejauh ini tidak ada yang rumit. Maka semuanya menjadi sederhana. Dengan analogi dengan produk, kami membuat implementasi berbeda dari pabrik kami untuk setiap OS. Mari kita mulai dengan Windows:
public class WindowsGUIFactory implements GUIFactory {
    public WindowsGUIFactory() {
        System.out.println("Creating gui factory for Windows OS");
    }

    public Button createButton() {
        System.out.println("Creating Button for Windows OS");
        return new WindowsButton();
    }

    public TextField createTextField() {
        System.out.println("Creating TextField for Windows OS");
        return new WindowsTextField();
    }

    public Select createSelect() {
        System.out.println("Creating Select for Windows OS");
        return new WindowsSelect();
    }
}
Output konsol di dalam metode dan konstruktor telah ditambahkan untuk mendemonstrasikan lebih lanjut cara kerjanya. Sekarang untuk macOS:
public class MacGUIFactory implements GUIFactory {
    public MacGUIFactory() {
        System.out.println("Creating gui factory for macOS");
    }

    @Override
    public Button createButton() {
        System.out.println("Creating Button for macOS");
        return new MacButton();
    }

    @Override
    public TextField createTextField() {
        System.out.println("Creating TextField for macOS");
        return new MacTextField();
    }

    @Override
    public Select createSelect() {
        System.out.println("Creating Select for macOS");
        return new MacSelect();
    }
}
Catatan: setiap metode, sesuai dengan tanda tangannya, mengembalikan tipe abstrak. Namun di dalam metode tersebut kami membuat implementasi produk yang konkrit. Ini adalah satu-satunya tempat di mana kami mengontrol pembuatan instance tertentu. Sekarang saatnya menulis formulir kelas. Ini adalah kelas Java yang bidangnya merupakan elemen antarmuka:
public class OrderCoffeeForm {
    private final TextField customerNameTextField;
    private final Select coffeTypeSelect;
    private final Button orderButton;

    public OrderCoffeeForm(GUIFactory factory) {
        System.out.println("Creating order coffee form");
        customerNameTextField = factory.createTextField();
        coffeTypeSelect = factory.createSelect();
        orderButton = factory.createButton();
    }
}
Pabrik abstrak diteruskan ke konstruktor formulir, yang membuat elemen antarmuka. Kami akan meneruskan implementasi pabrik yang diperlukan ke konstruktor sehingga kami dapat membuat elemen antarmuka untuk OS tertentu.
public class Application {
    private OrderCoffeeForm orderCoffeeForm;

    public void drawOrderCoffeeForm() {
        // Определим Name операционной системы, получив meaning системной проперти через System.getProperty
        String osName = System.getProperty("os.name").toLowerCase();
        GUIFactory guiFactory;

        if (osName.startsWith("win")) { // Для windows
            guiFactory = new WindowsGUIFactory();
        } else if (osName.startsWith("mac")) { // Для mac
            guiFactory = new MacGUIFactory();
        } else {
            System.out.println("Unknown OS, can't draw form :( ");
            return;
        }
        orderCoffeeForm = new OrderCoffeeForm(guiFactory);
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.drawOrderCoffeeForm();
    }
}
Jika kita menjalankan aplikasinya di Windows, kita akan mendapatkan output sebagai berikut:

Creating gui factory for Windows OS
Creating order coffee form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
Di Mac, outputnya adalah sebagai berikut:

Creating gui factory for macOS
Creating order coffee form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
Di Linux:

Unknown OS, can't draw form :( 
Baiklah, Anda dan saya menarik kesimpulan sebagai berikut. Kami menulis kerangka kerja untuk aplikasi GUI yang menciptakan elemen antarmuka yang sesuai untuk OS tertentu. Mari kita ulangi secara singkat apa yang kita buat:
  • Keluarga produk: bidang masukan, bidang pilihan, dan tombol.
  • Berbagai implementasi rangkaian produk ini, untuk Windows dan macOS.
  • Pabrik abstrak, tempat kami mendefinisikan antarmuka untuk membuat produk kami.
  • Dua implementasi pabrik kami, yang masing-masing bertanggung jawab untuk menciptakan rangkaian produk tertentu.
  • Formulir, kelas Java yang bidangnya merupakan elemen antarmuka abstrak yang diinisialisasi dalam konstruktor dengan nilai yang diperlukan menggunakan pabrik abstrak.
  • Kelas aplikasi. Di dalamnya, kami membuat formulir yang dengannya kami meneruskan implementasi yang diperlukan dari pabrik kami ke konstruktor.
Total: kami telah menerapkan pola pabrik abstrak.

Pabrik Abstrak: petunjuk penggunaan

Abstrak Pabrik adalah pola desain untuk mengelola penciptaan kelompok produk yang berbeda tanpa terikat pada kelas produk tertentu. Saat menggunakan templat ini, Anda harus:
  1. Tentukan sendiri kelompok produknya. Anggaplah kita mempunyai dua di antaranya:
    • SpecificProductA1,SpecificProductB1
    • SpecificProductA2,SpecificProductB2
  2. Untuk setiap produk dalam keluarga, tentukan kelas abstrak (antarmuka). Dalam kasus kami, ini adalah:
    • ProductA
    • ProductB
  3. Dalam setiap rangkaian produk, setiap produk harus mengimplementasikan antarmuka yang ditentukan pada langkah 2.
  4. Buat pabrik abstrak, dengan metode pembuatan untuk setiap produk yang ditentukan pada langkah 2. Dalam kasus kita, metode ini adalah:
    • ProductA createProductA();
    • ProductB createProductB();
  5. Buat implementasi pabrik abstrak sehingga setiap implementasi mengontrol pembuatan produk dari keluarga yang sama. Untuk melakukan ini, di dalam setiap implementasi pabrik abstrak, perlu untuk mengimplementasikan semua metode pembuatan, sehingga implementasi produk yang konkret dibuat dan dikembalikan ke dalamnya.
Di bawah ini adalah diagram UML yang mengilustrasikan instruksi yang dijelaskan di atas: Pola Desain: AbstrakPabrik - 3Sekarang mari kita tulis kode untuk instruksi ini:
// Определим общие интерфейсы продуктов
public interface ProductA {}
public interface ProductB {}

// Создадим различные реализации (семейства) наших продуктов
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}

public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}

// Создадим абстрактную фабрику
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory1 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB1();
    }
}

// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory2 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB2();
    }
}

Pekerjaan rumah

Untuk mengkonsolidasikan materi Anda dapat melakukan 2 hal:
  1. Memperbaiki aplikasi pemesanan kopi agar dapat berfungsi di Linux.
  2. Buat pabrik abstrak Anda sendiri untuk menghasilkan unit strategi apa pun. Ini bisa berupa strategi sejarah dengan tentara sungguhan atau fantasi dengan orc, kurcaci, dan elf. Yang penting menurut Anda itu menarik. Jadilah kreatif, pasang pin ke konsol, dan bersenang-senang mempelajari polanya!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION