CodeGym /Blog Java /rawak /Corak reka bentuk: Kilang abstrak
John Squirrels
Tahap
San Francisco

Corak reka bentuk: Kilang abstrak

Diterbitkan dalam kumpulan
Hai! Hari ini kita akan terus mengkaji corak reka bentuk dan kita akan membincangkan corak kilang abstrak . Corak reka bentuk: Kilang abstrak - 1Inilah yang akan kami bincangkan dalam pelajaran:
  • Kami akan membincangkan apa itu kilang abstrak dan masalah yang diselesaikan oleh corak ini
  • Kami akan mencipta rangka aplikasi merentas platform untuk memesan kopi melalui antara muka pengguna
  • Kami akan mengkaji arahan tentang cara menggunakan corak ini, termasuk melihat gambar rajah dan kod
  • Dan sebagai bonus, pelajaran ini termasuk telur Paskah tersembunyi yang akan membantu anda mempelajari cara menggunakan Java untuk menentukan nama sistem pengendalian dan, bergantung pada hasilnya, untuk melakukan satu sama lain tindakan atau yang lain.
Untuk memahami sepenuhnya corak ini, anda perlu mahir dalam topik berikut:
  • warisan di Jawa
  • kelas dan kaedah abstrak dalam Java

Apakah masalah yang diselesaikan oleh kilang abstrak?

Kilang abstrak, seperti semua corak kilang, membantu kami memastikan objek baharu dibuat dengan betul. Kami menggunakannya untuk menguruskan "pengeluaran" pelbagai keluarga objek yang saling berkaitan. Pelbagai keluarga objek yang saling berkaitan... Apakah maksudnya? Jangan risau: dalam amalan, semuanya lebih mudah daripada yang kelihatan. Sebagai permulaan, apakah keluarga objek yang saling berkaitan? Katakan kita sedang membangunkan strategi ketenteraan yang melibatkan beberapa jenis unit:
  • infantri
  • pasukan berkuda
  • pemanah
Jenis unit ini saling berkaitan, kerana mereka berkhidmat dalam tentera yang sama. Kita boleh mengatakan bahawa kategori yang disenaraikan di atas ialah keluarga objek yang saling berkaitan. Kami faham ini. Tetapi corak kilang abstrak digunakan untuk mengatur penciptaan pelbagai keluarga objek yang saling berkaitan. Tidak ada yang rumit di sini juga. Mari kita teruskan dengan contoh strategi ketenteraan. Secara umumnya, unit tentera tergolong dalam beberapa pihak yang berperang yang berbeza. Bergantung pada pihak mana mereka berada, unit tentera boleh berbeza dengan ketara dalam penampilan. Askar berjalan kaki, penunggang kuda dan pemanah tentera Rom tidak sama dengan tentera berjalan kaki, penunggang kuda dan pemanah Viking. Dalam strategi ketenteraan, askar tentera yang berbeza adalah keluarga objek yang saling berkaitan. Ia akan menjadi kelakar jika seorang pengaturcara' Kesilapan itu menyebabkan seorang askar berpakaian seragam Perancis era Napoleon, senapang siap, ditemui berjalan di antara barisan infantri Rom. Corak reka bentuk kilang abstrak diperlukan dengan tepat untuk menyelesaikan masalah ini. Tidak, bukan masalah malu yang boleh datang dari perjalanan masa, tetapi masalah mencipta pelbagai kumpulan objek yang saling berkaitan. Kilang abstrak menyediakan antara muka untuk mencipta semua produk yang tersedia (sebuah keluarga objek). Kilang abstrak biasanya mempunyai pelbagai pelaksanaan. Setiap daripada mereka bertanggungjawab untuk mencipta produk salah satu keluarga. Strategi ketenteraan kami termasuk kilang abstrak yang mencipta askar kaki abstrak, pemanah dan tentera berkuda, serta pelaksanaan kilang ini. Sebagai contoh, sebuah kilang yang mencipta legionnair Rom dan kilang yang mencipta askar Carthaginian. Abstraksi ialah prinsip panduan terpenting corak ini. Pelanggan kilang bekerja dengan kilang dan produknya hanya melalui antara muka abstrak. Akibatnya, anda tidak perlu memikirkan tentang askar yang sedang dicipta. Sebaliknya, anda menyerahkan tanggungjawab ini kepada beberapa pelaksanaan konkrit kilang abstrak.

Mari teruskan mengautomasikan kedai kopi kami

Dalam pelajaran lepas, kami mengkaji corak kaedah kilang. Kami menggunakannya untuk mengembangkan perniagaan kopi kami dan membuka beberapa lokasi baharu. Hari ini kami akan terus memodenkan perniagaan kami. Menggunakan corak kilang abstrak, kami akan meletakkan asas untuk aplikasi desktop baharu untuk memesan kopi dalam talian. Apabila menulis aplikasi desktop, kita harus sentiasa memikirkan tentang sokongan merentas platform. Aplikasi kami mesti berfungsi pada kedua-dua macOS dan Windows (spoiler: Sokongan untuk Linux ditinggalkan untuk anda laksanakan sebagai kerja rumah). Apakah rupa aplikasi kami? Agak mudah: ia akan menjadi borang yang terdiri daripada medan teks, medan pilihan dan butang. Jika anda mempunyai pengalaman menggunakan sistem pengendalian yang berbeza, anda pasti perasan bahawa butang pada Windows dipaparkan secara berbeza daripada pada Mac. Seperti yang lain... Baiklah, mari kita mulakan.
  • butang
  • medan teks
  • medan pemilihan
Penafian: Dalam setiap antara muka, kami boleh menentukan kaedah seperti onClick, onValueChanged, atau onInputChanged. Dalam erti kata lain, kita boleh menentukan kaedah yang membolehkan kita mengendalikan pelbagai acara (menekan butang, memasukkan teks, memilih nilai dalam kotak pilihan). Semua ini sengaja ditinggalkan di sini supaya tidak membebankan contoh dan menjadikannya lebih jelas semasa kita mengkaji corak kilang. Mari kita tentukan antara muka abstrak untuk produk kami:

public interface Button {}
public interface Select {}
public interface TextField {}
Untuk setiap sistem pengendalian, kita mesti mencipta elemen antara muka dalam gaya sistem pengendalian. Kami akan menulis kod untuk Windows dan MacOS. Mari buat pelaksanaan untuk Windows:

public class WindowsButton implements Button {
}

public class WindowsSelect implements Select {
}

public class WindowsTextField implements TextField {
}
Sekarang kita melakukan perkara yang sama untuk MacOS:

public class MacButton implements Button {
}

public class MacSelect implements Select {
}

public class MacTextField implements TextField {
}
Cemerlang. Kini kami boleh meneruskan ke kilang abstrak kami, yang akan mencipta semua jenis produk abstrak yang tersedia:

public interface GUIFactory {

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

}
Hebat. Seperti yang anda lihat, kami belum melakukan apa-apa yang rumit lagi. Semua yang berikut juga mudah. Dengan analogi dengan produk, kami mencipta pelbagai pelaksanaan kilang untuk setiap OS. Mari mulakan dengan Windows:

public class WindowsGUIFactory implements GUIFactory {
    public WindowsGUIFactory() {
        System.out.println("Creating GUIFactory 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();
    }
}
Kami telah menambah beberapa output konsol di dalam kaedah dan pembina untuk menggambarkan lebih lanjut apa yang sedang berlaku. Sekarang untuk macOS:

public class MacGUIFactory implements GUIFactory {
    public MacGUIFactory() {
        System.out.println("Creating GUIFactory 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();
    }
}
Ambil perhatian bahawa setiap tandatangan kaedah menunjukkan bahawa kaedah mengembalikan jenis abstrak. Tetapi di dalam kaedah, kami sedang mencipta pelaksanaan khusus produk. Ini adalah satu-satunya tempat kami mengawal penciptaan kejadian tertentu. Kini tiba masanya untuk menulis kelas untuk borang. Ini ialah kelas Java yang bidangnya adalah elemen antara muka:

public class CoffeeOrderForm {
    private final TextField customerNameTextField;
    private final Select coffeeTypeSelect;
    private final Button orderButton;

    public CoffeeOrderForm(GUIFactory factory) {
        System.out.println("Creating coffee order form");
        customerNameTextField = factory.createTextField();
        coffeeTypeSelect = factory.createSelect();
        orderButton = factory.createButton();
    }
}
Kilang abstrak yang mencipta elemen antara muka dihantar kepada pembina borang. Kami akan menyerahkan pelaksanaan kilang yang diperlukan kepada pembina untuk mencipta elemen antara muka untuk OS tertentu.

public class Application {
    private CoffeeOrderForm coffeeOrderForm;

    public void drawCoffeeOrderForm() {
        // Determine the name of the operating system through System.getProperty()
        String osName = System.getProperty("os.name").toLowerCase();
        GUIFactory guiFactory;

        if (osName.startsWith("win")) { // For Windows
            guiFactory = new WindowsGUIFactory();
        } else if (osName.startsWith("mac")) { // For Mac
            guiFactory = new MacGUIFactory();
        } else {
            System.out.println("Unknown OS. Unable to draw form :(");
            return;
        }
        coffeeOrderForm = new CoffeeOrderForm(guiFactory);
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.drawCoffeeOrderForm();
    }
}
Jika kami menjalankan aplikasi pada Windows, kami mendapat output berikut:

Creating GUIFactory for Windows OS
Creating coffee order form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
Pada Mac, output adalah seperti berikut:

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

Unknown OS. Unable to draw form :( 
Dan sekarang kita ringkaskan. Kami menulis rangka aplikasi berasaskan GUI di mana elemen antara muka dicipta khusus untuk OS yang berkaitan. Kami akan mengulangi secara ringkas apa yang telah kami buat:
  • Keluarga produk yang terdiri daripada medan input, medan pilihan dan butang.
  • Pelaksanaan berbeza keluarga produk untuk Windows dan macOS.
  • Kilang abstrak yang mentakrifkan antara muka untuk mencipta produk kami.
  • Dua pelaksanaan kilang kami, masing-masing bertanggungjawab untuk mencipta keluarga produk tertentu.
  • Borang (kelas Java) yang medannya adalah elemen antara muka abstrak yang dimulakan dengan nilai yang diperlukan dalam pembina menggunakan kilang abstrak.
  • Kelas aplikasi Di dalam kelas ini, kami mencipta borang, menghantar pelaksanaan kilang yang diingini kepada pembinanya.
Hasilnya ialah kami melaksanakan corak kilang abstrak.

Kilang abstrak: cara menggunakan

Kilang abstrak adalah corak reka bentuk untuk menguruskan penciptaan pelbagai keluarga produk tanpa terikat dengan kelas produk konkrit. Apabila menggunakan corak ini, anda mesti:
  1. Tentukan keluarga produk. Katakan kita mempunyai dua daripadanya:
    • SpecificProductA1,SpecificProductB1
    • SpecificProductA2,SpecificProductB2
  2. Untuk setiap produk dalam keluarga, tentukan kelas abstrak (antara muka). Dalam kes kami, kami mempunyai:
    • ProductA
    • ProductB
  3. Dalam setiap keluarga produk, setiap produk mesti melaksanakan antara muka yang ditakrifkan dalam langkah 2.
  4. Cipta kilang abstrak, dengan kaedah untuk mencipta setiap produk yang ditakrifkan dalam langkah 2. Dalam kes kami, kaedah ini ialah:
    • ProductA createProductA();
    • ProductB createProductB();
  5. Cipta pelaksanaan kilang abstrak supaya setiap pelaksanaan mengawal penciptaan produk satu keluarga. Untuk melakukan ini, di dalam setiap pelaksanaan kilang abstrak, anda perlu melaksanakan semua kaedah ciptaan supaya mereka mencipta dan mengembalikan pelaksanaan produk tertentu.
Gambar rajah UML berikut menggambarkan arahan yang digariskan di atas: Corak reka bentuk: Kilang abstrak - 3Sekarang kita akan menulis kod mengikut arahan ini:

    // Define common product interfaces
    public interface ProductA {}
    public interface ProductB {}

    // Create various implementations (families) of our products
    public class SpecificProductA1 implements ProductA {}
    public class SpecificProductB1 implements ProductB {}

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

    // Create an abstract factory
    public interface AbstractFactory {
        ProductA createProductA();
        ProductB createProductB();
    }

    // Implement the abstract factory in order to create products in family 1
    public class SpecificFactory1 implements AbstractFactory {

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

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

    // Implement the abstract factory in order to create products in family 2
    public class SpecificFactory2 implements AbstractFactory {

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

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

Kerja rumah

Untuk mengukuhkan bahan, anda boleh melakukan 2 perkara:
  1. Perhalusi aplikasi pesanan kopi supaya ia juga berfungsi pada Linux.
  2. Cipta kilang abstrak anda sendiri untuk menghasilkan unit yang terlibat dalam sebarang strategi ketenteraan. Ini boleh sama ada strategi ketenteraan sejarah yang melibatkan tentera sebenar, atau fantasi dengan orc, gnome dan bunian. Perkara utama ialah memilih sesuatu yang menarik minat anda. Jadi kreatif, cetak mesej pada konsol dan nikmati pembelajaran tentang corak!
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION