JavaRush /Blog Java /Random-MS /Kaedah Kilang dan Corak Kilang Abstrak

Kaedah Kilang dan Corak Kilang Abstrak

Diterbitkan dalam kumpulan
Dalam buku “Kepala Didahulukan. Corak Reka Bentuk” mentakrifkan corak ini seperti berikut: Corak Kaedah Kilang mentakrifkan antara muka untuk mencipta objek, tetapi membenarkan subkelas memilih kelas contoh yang akan dibuat. Oleh itu, kaedah Kilang mewakilkan operasi instantiasi kepada subkelas. Corak Kilang Abstrak menyediakan antara muka untuk mencipta keluarga objek yang saling berkaitan atau saling bergantung tanpa menyatakan kelas konkritnya. Mari cuba memahami perkara ini dengan lebih terperinci. Katakan anda memutuskan untuk menulis permainan tentang orang yang memutuskan untuk menjadi... (anda memerlukan sesuatu yang asli dan luar biasa di sini) sami. Kita boleh mulakan dengan yang berikut. 1) Buat kelas Monk dan kelas kanak-kanak (mari buat satu dahulu):
public abstract class Monk {

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я православный монах");
    }
}
2) Dan sudah tentu, buat kelas Biara, di mana anda boleh melaksanakan "ikrar biara":
public class Monastery {
    private Monk monk;

    public void createMonk(String typeName) {
        this.monk = switch (typeName) {
            case "ORTODOX" -> new OrthodoxMonk();
            default -> null;
        };
    }

    public Monk getMonk() {
        return monk;
    }
}
Nah, mari kita semak hasilnya:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new Monastery();
        monastery.createMonk("ORTODOX");
        monastery.getMonk().description();
    }
}
Я православный монах
Sekarang jika anda perlu mencipta... sami Katolik, anda perlu A) Buat kelas baharu untuk sami Katolik:
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
B) Buat perubahan pada kelas biara:
public class Monastery {
    private Monk monk;

    public void createMonk(String typeName) {
        this.monk = switch (typeName) {
            case "ORTODOX" -> new OrthodoxMonk();
            case "CATHOLIC" -> new CatholicMonk();
            default -> null;
        };
    }

    public Monk getMonk() {
        return monk;
    }
}
maka setiap kali jenis sami baharu diperkenalkan, anda perlu membuat kelas baharu dan mengedit kelas sedia ada. Apa yang boleh dilakukan dalam kes ini untuk "merangkum" kelas biara kita daripada perubahan. Anda boleh cuba menggunakan corak Kaedah Kilang. Bagaimana ia akan kelihatan A) Mari kita tinggalkan kelas sami seperti sedia ada, kecuali mungkin tambah seorang sami Anglikan (bukan sahaja penganut Katolik dan Kristian Ortodoks mempunyai monastik):
public abstract class Monk {

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я православный монах");
    }
}
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
public class AnglicanMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я англиканский монах");
    }
}
B) Mari kita ubah kelas biara seperti berikut (mari jadikan ia dan kaedahnya abstrak). Di sini kita hanya menggunakan kaedah Kilang:
public abstract class Monastery {
    protected abstract Monk createMonk();
}
dan buat kelas kanak-kanak dengan pelaksanaan kaedah:
public class OrthodoxMonastery extends Monastery {
    @Override
    protected Monk createMonk() {
        return new OrthodoxMonk();
    }
}
public class CatholicMonastery extends Monastery {
    @Override
    protected Monk createMonk() {
        return new CatholicMonk();
    }
}
public class AnglicanMonastery extends Monastery {
    @Override
    protected Monk createMonk() {
        return new AnglicanMonk();
    }
}
B) Mari kita semak kod
public class Main {
    public static void main(String[] args) {
        Monastery monastery;

        monastery = new OrthodoxMonastery();
        monastery.createMonk().description();

        monastery = new CatholicMonastery();
        monastery.createMonk().description();

        monastery = new AnglicanMonastery();
        monastery.createMonk().description();
    }
}
Я православный монах
Я католический монах
Я англиканский монах
Itu. seperti yang kita lihat sekarang, apabila menambah jenis baru sami, tidak perlu menukar kelas sedia ada, tetapi hanya jika perlu, menambah yang baru (kelas biara dan sami tertentu). Mungkin seseorang telah menyedari bahawa kaedah penerangan, yang sejak awal lagi dalam kelas Monk, juga adalah Kilang :) Takrifan kaedah kilang mengatakan bahawa corak kami mentakrifkan antara muka untuk mencipta objek, tetapi kami tidak mencipta sebarang antara muka, walaupun kita boleh mencipta kelas Biara sebagai antara muka dan melaksanakannya dalam pelaksanaan tertentu. Ini merujuk kepada perkataan "antara muka" dalam erti kata yang lebih luas. Takrifan itu juga mengatakan bahawa ia membenarkan subkelas untuk memilih kelas bagi contoh yang mereka cipta . Di sini kita hanya melihat bahawa subkelas (kelas kanak-kanak) melaksanakan kaedah ini (iaitu, kuasa ini untuk mencipta objek sami diwakilkan kepada mereka). Sekarang mari kita kembangkan sedikit program kita, perkenalkan kemungkinan terdapat bhikkhu yang berbeza dalam satu denominasi atau yang lain. Sebagai contoh, dalam Ortodoks, berdasarkan kedudukan Gereja Ortodoks di biara dan biara (yang diterima pakai di Majlis Uskup Gereja Ortodoks Rusia pada 29 November - 2 Disember 2017), kita boleh membuat kesimpulan bahawa terdapat 2 jenis sami. : - Skema yang lebih kecil (mantel). - Skema (skema hebat). Terdapat juga "peringkat persediaan", tetapi orang tidak dianggap sebagai bhikkhu (Trudnik, Novice dan Ryasophor atau Monk), kerana mereka tidak mengambil ikrar monastik. Oleh itu, kami tidak mengambil kira mereka. Apa yang kita dapat dalam kes ini: A) Kelas Biara (untuk memudahkan, mari fokus pada monastik Ortodoks buat masa ini) dengan kaedah Kilang :
public abstract class Monastery {
    protected abstract Monk createMonk(String type);
}
dan biara tertentu
public class OrthodoxMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new OrthodoxMonk(type);
    }
}
B) Mari kita betulkan kelas sami:
public abstract class Monk {
    String kind;

    public Monk(String kind) {
        this.kind = kind;
    }

    public abstract void description();
}
dan kelas kanak-kanak:
public class OrthodoxMonk extends Monk {
    public OrthodoxMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
    }
}
C) Mari semak kod kami:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
Oleh itu, dengan menggunakan corak Kaedah Kilang, kami mencapai bahawa kami tidak perlu menukar kelas yang ditulis sebelum ini, tetapi juga apabila mengembangkan imej (jenis) sami, perubahan minimum dalam kod diperlukan. Mari kita semak dan tambah semua perintah dan jemaah sami Katolik :) Tetapi lebih baik untuk memberi tumpuan kepada 3 yang paling terkenal, kerana terdapat lebih daripada 100 daripada mereka: 1) Benedictine 2) Jesuit 3) Franciscan Untuk melakukan ini, seperti sebelum ini dengan sami Ortodoks, kita perlu melaksanakan kelas khusus sami Katolik:
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я католический монах - " + kind);
    }
}
dan kelas biara:
public class CatholicMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new CatholicMonk(type);
    }
}
dan semak kod:
public class Main {
    public static void main(String[] args) {
        Monastery monastery;

        monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();

        monastery = new CatholicMonastery();
        monastery.createMonk("Бенедиктинец").description();
        monastery.createMonk("Иезуит").description();
        monastery.createMonk("Францисканец").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах - Великосхимник
Я католический монах - Бенедиктинец
Я католический монах - Иезуит
Я католический монах - Францисканец
Mari kita selesaikan dengan corak ini. Semua jenis sami ini juga boleh ditambahkan ke kelas E-num terlebih dahulu, tetapi untuk memudahkan kod kita akan lakukan tanpa itu. Sudah tiba masanya untuk corak Kilang Abstrak. Kami mempunyai sami, kini kami boleh membuat pakaian, tasbih, dll. Mari kita mulakan dengan pakaian, iaitu, jika kita kembali kepada definisi kita pada mulanya, pakaian akan menjadi satu keluarga objek yang saling berkaitan atau saling bergantung . Mari kita mulakan dengan masalah bahawa setiap jenis sami mempunyai jubah yang berbeza. Jika kita juga menambah Buddha, maka mereka akan berbeza sama sekali :) Untuk melakukan ini, kita boleh membuat antara muka kilang, pelaksanaannya akan mencipta pakaian yang diperlukan. Oleh itu A) Kami mewujudkan kilang untuk membuat pakaian
public interface MonkFactory {
    Clothing createClothing();
}
dan pelaksanaannya
public class OrthodoxMonkFactory implements MonkFactory {

        @Override
    public Clothing createClothing() {
        return new OrtodoxClothing();
    }
}
public class CatholicMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new CatholicClothing();
    }
}
public class AnglicanMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new AnglicanClothing();
    }
}
Nah, jangan lupa tentang sami Buddha :)
public class BuddhistMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new BuddhistClothing();
    }
}
B) Buat kelas pakaian (untuk memudahkan, mari kita ambil elemen utama pakaian sami, kita tidak akan menjelaskan secara terperinci):
public abstract class Clothing {
    private String name;

    public Clothing(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
dan kelas kanak-kanak
public class OrtodoxClothing extends Clothing {
    public OrtodoxClothing() {
        super("Мантия");
    }
}
public class CatholicClothing extends Clothing {
    public CatholicClothing() {
        super("Ряса с капюшоном");
    }
}
public class AnglicanClothing extends Clothing {
    public AnglicanClothing() {
        super("Ряса");
    }
}
public class BuddhistClothing extends Clothing {
    public BuddhistClothing() {
        super("Кашая");
    }
}
C) Seterusnya, kami menukar kelas para bhikkhu supaya mereka mempunyai pakaian:
public abstract class Monk {
    String kind;
    Clothing clothing;

    public Monk(String kind) {
        this.kind = kind;
    }

    public void setClothing(Clothing clothing) {
        this.clothing = clothing;
    }

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    public OrthodoxMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }
}
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я католический монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }
}
public class AnglicanMonk extends Monk {
    public AnglicanMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я англиканский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }
}
public class BuddhistMonk extends Monk {
    public BuddhistMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я буддийский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }
}
D) Kelas biara mengandungi kaedah Kilang kami
public abstract class Monastery {

    public Monk create(MonkFactory monkFactory, String type) {
        Monk monk = createMonk(type);
        monk.setClothing(monkFactory.createClothing());
        return monk;
    }

    protected abstract Monk createMonk(String type);
}
pelaksanaan kami tidak berubah
public class OrthodoxMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new OrthodoxMonk(type);
    }
}
public class CatholicMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new CatholicMonk(type);
    }
}
public class AnglicanMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new AnglicanMonk(type);
    }
}
public class BuddhistMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new BuddhistMonk(type);
    }
}
D) Semak keputusan:
public class Main {
    public static void main(String[] args) {
        Monastery monastery;

        monastery = new OrthodoxMonastery();
        monastery.create(new OrthodoxMonkFactory(), "Мантийный монах").description();

        monastery = new CatholicMonastery();
        monastery.create(new CatholicMonkFactory(), "Иезуит").description();

        monastery = new AnglicanMonastery();
        monastery.create(new AnglicanMonkFactory(), "Бенедиктинец").description();

        monastery = new BuddhistMonastery();
        monastery.create(new BuddhistMonkFactory(), "Монах").description();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Kilang yang mencipta pakaian telah mula berfungsi dengan baik. Kini anda boleh menambah kilang pengeluaran peralatan untuk sami untuk solat yang berjaya (manik tasbih, dll.). Tetapi persoalannya masih kekal, adakah mungkin untuk menggunakan 2 corak bersama? Sudah tentu anda boleh :) Mari cuba buat versi akhir projek kami dan tambahkan sami Hindu: A) Kilang kini mencipta sami bunyi seperti "kilang bintang" :
public interface MonkFactory {
    Monk createMonk(String type);
    Clothing createClothing();
}
public class OrthodoxMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new OrthodoxMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new OrtodoxClothing();
    }
}
public class CatholicMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new CatholicMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new CatholicClothing();
    }
}
public class AnglicanMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new AnglicanMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new AnglicanClothing();
    }
}
public class BuddhistMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new BuddhistMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new BuddhistClothing();
    }
}
public class HinduMonkFactory implements MonkFactory {

    @Override
    public Monk createMonk(String type){
        return new HinduMonk(type);
    }

    @Override
    public Clothing createClothing() {
        return new HinduClothing();
    }
}
B) Kelas biara + pelaksanaan konkrit kelas Biara tidak diperlukan, ia dilaksanakan oleh kilang (sebaliknya, kita boleh meninggalkannya dan mengalih keluar kilang, tetapi pada dasarnya mereka kemudiannya akan menjadi bukan kilang, hanya dalam kes ini Biara kemudiannya perlu dibuat antara muka, dan bukan kelas abstrak). Dan tambahkan kelas aplikasi:
public class Application {

    public Monk create(MonkFactory monkFactory, String type) {
        Monk monk = monkFactory.createMonk(type);
        monk.prepare(monkFactory);
        return monk;
    }
}
B) Bhikkhu kini mengandungi
public abstract class Monk {
    String kind;
    Clothing clothing;

    public Monk(String kind) {
        this.kind = kind;
    }

    public void setClothing(Clothing clothing) {
        this.clothing = clothing;
    }

    public abstract void description();

    public abstract void prepare(MonkFactory monkFactory);
}
mengandungi kaedah kilang dalam pelaksanaan, yang dilaksanakan menggunakan kilang:
public class OrthodoxMonk extends Monk {

    public OrthodoxMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я католический монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
public class AnglicanMonk extends Monk {
    public AnglicanMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я англиканский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
public class BuddhistMonk extends Monk {
    public BuddhistMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я буддийский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
public class HinduMonk extends Monk {
    public HinduMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я индуистский монах - " + kind);
        System.out.println("Моя одежда - " + clothing.getName());
    }

    @Override
    public void prepare(MonkFactory monkFactory) {
        setClothing(monkFactory.createClothing());
    }
}
D) Dan mari kita semak:
public class Main {
    public static void main(String[] args) {
        Application application = new Application();

        application.create(new OrthodoxMonkFactory(), "Мантийный монах").description();
        application.create(new CatholicMonkFactory(), "Иезуит").description();
        application.create(new AnglicanMonkFactory(), "Бенедиктинец").description();
        application.create(new BuddhistMonkFactory(), "Монах").description();
        application.create(new HinduMonkFactory(), "Саньяси").description();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
Sebagai kesimpulan, anda boleh ambil perhatian bahawa kaedah Kilang menggunakan kelas abstrak dengan kaedah yang tidak dilaksanakan, yang dilaksanakan dalam subkelas, dan Kilang Abstrak menggunakan antara muka, di mana pelaksanaan (dalam kes kami, mencipta sami) berlaku dalam kelas yang dilaksanakan. antara muka ini.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION