JavaRush /Blog Java /Random-MS /Corak Reka Bentuk: FactoryMethod

Corak Reka Bentuk: FactoryMethod

Diterbitkan dalam kumpulan
hello! Hari ini kita akan terus mengkaji corak reka bentuk dan bercakap tentang Kaedah Kilang. Corak Reka Bentuk: Kaedah Kilang - 1Anda akan mengetahui apa itu dan apa tugas templat ini sesuai untuknya. Kami akan melihat corak reka bentuk ini secara praktikal dan meneroka strukturnya. Untuk membuat semua perkara di atas jelas kepada anda, anda perlu memahami topik berikut:
  1. Warisan di Jawa.
  2. Kaedah dan kelas abstrak di Jawa.

Apakah masalah yang diselesaikan oleh kaedah kilang?

Dalam semua corak reka bentuk kilang, terdapat dua kumpulan peserta - pencipta (kilang itu sendiri) dan produk (objek yang dicipta oleh kilang). Bayangkan keadaannya: kami mempunyai kilang yang mengeluarkan kereta di bawah jenama AutoRush. Dia tahu cara mencipta model kereta dengan pelbagai jenis badan:
  • kereta sedan
  • gerabak stesen
  • coupe
Segalanya berjalan lancar untuk kami sehingga satu hari yang baik kami menyerap kebimbangan OneAuto. Sebagai pengurus yang bijak, kami tidak mahu kehilangan pelanggan OneAuto dan tugas kami adalah untuk menstruktur semula pengeluaran dengan cara yang kami boleh menghasilkan:
  • kereta sedan AutoRush
  • Kereta stesen AutoRush
  • coupe AutoRush
  • kereta sedan OneAuto
  • Gerabak stesen OneAuto
  • coupe OneAuto
Seperti yang anda lihat, bukannya satu kumpulan produk derivatif, dua muncul, yang berbeza dalam beberapa butiran. Corak reka bentuk kaedah kilang menyelesaikan masalah mencipta kumpulan produk yang berbeza, masing-masing dengan beberapa kekhususan. Kami akan mempertimbangkan prinsip templat ini dalam amalan, secara beransur-ansur beralih daripada mudah kepada kompleks, menggunakan contoh kedai kopi kami, yang kami buat dalam salah satu kuliah sebelumnya .

Sedikit tentang templat kilang

Biar saya ingatkan anda: kami membina kedai kopi maya kecil dengan anda. Di dalamnya, kami belajar cara mencipta pelbagai jenis kopi menggunakan kilang yang ringkas. Hari ini kita akan memperhalusi contoh ini. Mari kita ingat bagaimana rupa kedai kopi kita dengan kilang yang ringkas. Kami mempunyai kelas kopi:
public class Coffee {
    public void grindCoffee(){
        // перемалываем кофе
    }
    public void makeCoffee(){
        // делаем кофе
    }
    public void pourIntoCup(){
        // наливаем в чашку
    }
}
Dan juga beberapa ahli warisnya - jenis kopi tertentu yang boleh dihasilkan oleh kilang kami:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Untuk kemudahan menerima tempahan, kami telah memperkenalkan pemindahan:
public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}
Kilang kopi itu sendiri kelihatan seperti ini:
public class SimpleCoffeeFactory {
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new Americano();
                break;
            case ESPRESSO:
                coffee = new Espresso();
                break;
            case CAPPUCCINO:
                coffee = new Cappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new CaffeLatte();
                break;
        }

        return coffee;
    }
}
Dan akhirnya, kedai kopi itu sendiri:
public class CoffeeShop {

    private final SimpleCoffeeFactory coffeeFactory;

    public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
        this.coffeeFactory = coffeeFactory;
    }

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = coffeeFactory.createCoffee(type);
        coffee.grindCoffee();
        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
        return coffee;
    }
}

Pemodenan kilang ringkas

Kedai kopi kami berjalan lancar. Sehinggakan kami terfikir untuk meluaskan. Kami mahu membuka beberapa mata baru. Sebagai lelaki yang berdaya usaha, kami tidak akan membuat kedai kopi yang membosankan. Saya mahu setiap orang mempunyai kelainan tersendiri. Oleh itu, sebagai permulaan, kami akan membuka dua mata: dalam gaya Itali dan Amerika. Perubahan akan menjejaskan bukan sahaja bahagian dalam, tetapi juga minuman:
  • di kedai kopi Itali kami akan menggunakan jenama kopi Itali secara eksklusif, dengan pengisaran dan pemanggangan istimewa.
  • Bahagian Amerika akan menjadi lebih besar sedikit, dan dengan setiap pesanan kami akan menyajikan marshmallow cair - marshmallow.
Satu-satunya perkara yang akan kekal tidak berubah ialah model perniagaan kami, yang telah membuktikan dirinya dengan baik. Jika kita bercakap dalam bahasa kod, inilah yang berlaku. Kami mempunyai 4 kelas produk:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Dan ia menjadi 8:
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}

public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
Memandangkan kami mahu mengekalkan model perniagaan semasa tidak berubah, kami mahu kaedah itu orderCoffee(CoffeeType type)mengalami bilangan perubahan minimum. Mari kita lihat:
public Coffee orderCoffee(CoffeeType type) {
    Coffee coffee = coffeeFactory.createCoffee(type);
    coffee.grindCoffee();
    coffee.makeCoffee();
    coffee.pourIntoCup();

    System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
    return coffee;
}
Apakah pilihan yang kita ada? Kita dah tahu menulis kilang kan? Perkara paling mudah yang segera terlintas di fikiran ialah menulis dua kilang yang serupa, dan kemudian lulus pelaksanaan yang diperlukan ke kedai kopi kami dalam pembina. Kemudian kelas kedai kopi tidak akan berubah. Pertama, kita perlu mencipta kelas kilang baharu, mewarisi daripada kilang ringkas kami dan mengatasi createCoffee (CoffeeType type). Mari kita tulis kilang untuk membuat kopi dalam gaya Itali dan Amerika:
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}

public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }

}
Kini kita boleh menghantar pelaksanaan kilang yang diperlukan kepada CoffeeShop. Mari lihat rupa kod untuk memesan kopi dari kedai kopi yang berbeza. Contohnya, cappuccino dalam gaya Itali dan Amerika:
public class Main {
    public static void main(String[] args) {
        /*
            Закажем капучино в итальянском стиле:
            1. Создадим фабрику для приготовления итальянского кофе
            2. Создадим новую кофейню, передав ей в конструкторе фабрику итальянского кофе
            3. Закажем наш кофе
         */
        SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
        CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
        italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);


         /*
            Закажем капучино в американском стиле
            1. Создадим фабрику для приготовления американского кофе
            2. Создадим новую кофейню, передав ей в конструкторе фабрику американского кофе
            3. Закажем наш кофе
         */
        SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
        CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
        americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
    }
}
Kami mencipta dua kedai kopi berbeza, memindahkan setiap kedai ke kilang yang diperlukan. Di satu pihak, kita telah mencapai matlamat kita, tetapi di sisi lain... Ada sesuatu yang mengguris jiwa usahawan yang tidak dapat ditekan... Mari kita fikirkan apa yang salah. Pertama, banyaknya kilang. Adakah mungkin untuk membuat kilang anda sendiri setiap kali untuk titik baru dan, sebagai tambahan, pastikan bahawa apabila membuat kedai kopi, kilang yang diperlukan dipindahkan ke pembina? Kedua, ia masih kilang yang mudah. Cuma dimodenkan sedikit. Kami masih mengkaji corak baru di sini. Ketiga, bukankah mungkin untuk melakukannya secara berbeza? Alangkah baiknya jika kita boleh menyetempatkan semua soalan tentang membuat kopi di dalam bilik darjah CoffeeShop, menghubungkan proses membuat kopi dan menyediakan pesanan, tetapi pada masa yang sama mengekalkan fleksibiliti yang mencukupi untuk membuat kopi dalam gaya yang berbeza. Jawapannya ya, boleh. Ini dipanggil corak reka bentuk kaedah kilang.

Dari kilang yang mudah kepada kaedah kilang

Untuk menyelesaikan masalah secekap mungkin, kami:
  1. Mari kita kembalikan kaedah createCoffee(CoffeeType type)kepada kelas CoffeeShop.
  2. Mari jadikan kaedah ini abstrak.
  3. Kelas itu sendiri CoffeeShopakan menjadi abstrak.
  4. Kelas CoffeeShopakan mempunyai waris.
Ya kawan. Kedai kopi Itali tidak lebih daripada pewaris kelas CoffeeShop, melaksanakan kaedah createCoffee(CoffeeType type)mengikut tradisi terbaik barista Itali. Jadi, mengikut urutan. Langkah 1. Mari jadikan kelas Coffeeabstrak. Kami kini mempunyai dua keluarga produk yang berbeza. Minuman kopi Itali dan Amerika masih berkongsi nenek moyang yang sama: Coffee. Adalah betul untuk menjadikannya abstrak:
public abstract class Coffee {
    public void makeCoffee(){
        // делаем кофе
    }
    public void pourIntoCup(){
        // наливаем в чашку
    }
}
Langkah 2. Jadikan ia CoffeeShopabstrak, dengan kaedah abstrakcreateCoffee(CoffeeType type)
public abstract class CoffeeShop {

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = createCoffee(type);

        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
        return coffee;
    }

    protected abstract Coffee createCoffee(CoffeeType type);
}
Langkah 3. Cipta kedai kopi Itali, kelas keturunan kedai kopi abstrak. Di dalamnya kami melaksanakan kaedah createCoffee(CoffeeType type)dengan mengambil kira spesifik Itali.
public class ItalianCoffeeShop extends CoffeeShop {

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}
Langkah 4. Mari kita lakukan perkara yang sama untuk kedai kopi gaya Amerika.
public class AmericanCoffeeShop extends CoffeeShop {
    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }
}
Langkah 5. Mari kita lihat bagaimana pesanan latte gaya Amerika dan Itali akan kelihatan seperti:
public class Main {
    public static void main(String[] args) {
        CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
        italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);

        CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
        americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
    }
}
tahniah. Kami baru sahaja melaksanakan corak reka bentuk kaedah kilang di kedai kopi kami.

Bagaimana kaedah kilang berfungsi

Sekarang mari kita lihat lebih dekat apa yang kita dapat. Rajah di bawah menunjukkan kelas yang terhasil. Blok hijau ialah kelas pencipta, blok biru ialah kelas produk. Corak Reka Bentuk: Kaedah Kilang - 2Apakah kesimpulan yang boleh dibuat?
  1. Semua produk adalah pelaksanaan kelas abstrak Coffee.
  2. Semua pencipta adalah pelaksanaan kelas abstrak CoffeeShop.
  3. Kami memerhatikan dua hierarki kelas selari:
    • Hierarki produk. Kami melihat keturunan Itali dan keturunan Amerika
    • Hierarki pencipta. Kami melihat keturunan Itali dan keturunan Amerika
  4. Superclass CoffeeShoptidak mempunyai maklumat tentang pelaksanaan produk tertentu ( Coffee) yang akan dibuat.
  5. Kelas super CoffeeShopmewakilkan penciptaan produk tertentu kepada keturunannya.
  6. Setiap kelas keturunan CoffeeShopmelaksanakan kaedah kilang createCoffee()mengikut spesifikasinya. Dalam erti kata lain, dalam pelaksanaan kelas pencipta, keputusan dibuat untuk menyediakan produk khusus berdasarkan spesifikasi kelas pencipta.
Kini anda sudah bersedia untuk menentukan corak kaedah kilang . Corak kaedah kilang mentakrifkan antara muka untuk mencipta objek, tetapi membenarkan subkelas memilih kelas contoh untuk dibuat. Oleh itu, kaedah Kilang mewakilkan operasi instantiasi kepada subkelas. Secara umum, mengingati definisi tidak sepenting memahami cara sesuatu berfungsi.

Struktur kaedah kilang

Corak Reka Bentuk: FactoryMethod - 3Rajah di atas menunjukkan struktur umum corak kaedah kilang. Apa lagi yang penting di sini?
  1. Kelas Pencipta mengandungi pelaksanaan semua kaedah yang berinteraksi dengan produk, kecuali kaedah kilang.
  2. Kaedah abstrak factoryMethod()mesti dilaksanakan oleh semua keturunan kelas Creator.
  3. Kelas ConcreteCreatormelaksanakan kaedah factoryMethod()yang secara langsung menghasilkan produk.
  4. Kelas ini bertanggungjawab untuk mencipta produk tertentu. Ini adalah satu-satunya kelas dengan maklumat tentang mencipta produk ini.
  5. Semua produk mesti melaksanakan antara muka biasa - menjadi keturunan kelas produk biasa. Ini adalah perlu supaya kelas yang menggunakan produk boleh beroperasi pada mereka pada tahap abstraksi dan bukannya pelaksanaan konkrit.

Kerja rumah

Jadi, hari ini kami melakukan banyak kerja dan mengkaji corak reka bentuk kaedah kilang. Sudah tiba masanya untuk menyatukan bahan yang telah anda bincangkan! Tugasan 1. Bekerjasama membuka kedai kopi lain. Ia boleh dibuat dalam gaya Inggeris atau Sepanyol. Ataupun dalam gaya kapal angkasa. Mari tambah pewarna makanan pada kopi untuk menjadikannya bersinar, dan secara amnya, kopi akan menjadi ruang sahaja! Tugasan 2. Pada kuliah terakhir, anda mempunyai tugas untuk mencipta bar sushi maya atau restoran pizza maya. Tugas anda adalah untuk tidak berdiam diri. Hari ini anda belajar bagaimana anda boleh menggunakan corak kaedah kilang untuk mencapai kejayaan. Sudah tiba masanya untuk memanfaatkan ilmu ini dan mengembangkan perniagaan anda sendiri ;)
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION