JavaRush /Java Blog /Random-ID /Metode Pabrik dan Pola Pabrik Abstrak

Metode Pabrik dan Pola Pabrik Abstrak

Dipublikasikan di grup Random-ID
Dalam buku “Kepala Pertama. Pola Desain” mendefinisikan pola-pola ini sebagai berikut: Pola Metode Pabrik mendefinisikan antarmuka untuk membuat objek, tetapi memungkinkan subkelas untuk memilih kelas dari instance yang akan dibuat. Dengan demikian, metode Pabrik mendelegasikan operasi instantiasi ke subkelas. Pola Pabrik Abstrak menyediakan antarmuka untuk membuat kumpulan objek yang saling terkait atau saling bergantung tanpa menentukan kelas konkritnya. Mari kita coba memahaminya lebih detail. Katakanlah Anda memutuskan untuk menulis permainan tentang orang-orang yang memutuskan untuk menjadi... (Anda memerlukan sesuatu yang orisinal dan tidak biasa di sini) biksu. Kita bisa memulainya dengan hal berikut ini. 1) Buat kelas Monk dan kelas anak (mari kita buat terlebih dahulu):
public abstract class Monk {

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я православный монах");
    }
}
2) Dan tentu saja, buatlah kelas Biara, di mana Anda dapat melaksanakan “sumpah 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;
    }
}
Baiklah, mari kita periksa hasilnya:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new Monastery();
        monastery.createMonk("ORTODOX");
        monastery.getMonk().description();
    }
}
Я православный монах
Sekarang jika Anda perlu membuat... seorang biarawan Katolik, Anda perlu A) Membuat kelas baru untuk seorang biarawan Katolik:
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
B) Melakukan 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;
    }
}
jadi setiap kali tipe biksu baru diperkenalkan, Anda harus membuat kelas baru dan mengedit kelas yang sudah ada. Apa yang bisa dilakukan dalam kasus ini untuk “merangkum” kelas biara kita dari perubahan. Anda dapat mencoba menggunakan pola Metode Pabrik. Bagaimana tampilannya A) Mari kita biarkan kelas biarawan apa adanya, kecuali mungkin menambahkan seorang biarawan Anglikan (tidak hanya Katolik dan Kristen Ortodoks yang memiliki monastisisme):
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 sebagai berikut (mari kita buat dan metodenya abstrak). Di sini kita hanya menggunakan metode Pabrik:
public abstract class Monastery {
    protected abstract Monk createMonk();
}
dan buat kelas anak dengan implementasi metode:
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 periksa kodenya
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, ketika menambah jenis biksu baru, tidak perlu mengubah kelas yang sudah ada, tetapi hanya jika perlu, menambah kelas baru (kelas biara dan biksu tertentu). Mungkin seseorang telah memperhatikan bahwa metode deskripsi, yang sejak awal ada di kelas Monk, juga merupakan Pabrik :) Definisi metode pabrik mengatakan bahwa pola kami mendefinisikan antarmuka untuk membuat objek, tetapi kami tidak membuat apa pun antarmuka, meskipun kita dapat membuat kelas Monastery sebagai antarmuka dan mengimplementasikannya dalam implementasi tertentu. Ini mengacu pada kata “antarmuka” dalam arti yang lebih luas. Definisi tersebut juga mengatakan bahwa hal itu memungkinkan subkelas untuk memilih kelas dari instance yang mereka buat . Di sini kita hanya melihat bahwa subkelas (kelas anak) mengimplementasikan metode ini (yaitu, wewenang untuk membuat objek biksu didelegasikan kepada mereka). Sekarang mari kita kembangkan sedikit program kita, perkenalkan kemungkinan adanya biksu yang berbeda dalam satu denominasi atau denominasi lainnya. Misalnya, dalam Ortodoksi, berdasarkan posisi Gereja Ortodoks terhadap biara dan biara (diadopsi pada Dewan Uskup Gereja Ortodoks Rusia pada 29 November - 2 Desember 2017), kita dapat menyimpulkan bahwa ada 2 jenis biksu. : - Skema yang lebih kecil (mantel). - Skema (skema hebat). Ada juga “tahap persiapan”, tetapi orang tidak dianggap biksu (Trudnik, Pemula dan Ryasophor atau Biksu), karena mereka tidak mengambil sumpah biara. Oleh karena itu, kami tidak memperhitungkannya. Apa yang kita dapatkan dalam kasus ini: A) Kelas Biara (untuk menyederhanakan, mari kita fokus pada monastisisme Ortodoks untuk saat ini) dengan metode Pabrik :
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 perbaiki kelas biksu:
public abstract class Monk {
    String kind;

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

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

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
    }
}
C) Mari kita periksa kode kita:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
Jadi, dengan menggunakan pola Metode Pabrik, kami mencapai bahwa kami tidak harus mengubah kelas yang ditulis sebelumnya, tetapi juga ketika memperluas gambar (tipe) biksu, diperlukan sedikit perubahan pada kode. Mari kita periksa dan tambahkan semua ordo dan kongregasi biarawan Katolik :) Tapi lebih baik fokus pada 3 yang paling terkenal, karena ada lebih dari 100 di antaranya: 1) Benediktin 2) Jesuit 3) Fransiskan Untuk melakukan ini, seperti sebelumnya dengan untuk biksu Ortodoks, kita perlu menerapkan kelas biksu Katolik tertentu:
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 periksa kodenya:
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 pola ini. Semua tipe biksu ini juga dapat ditambahkan ke kelas E-num terlebih dahulu, tetapi untuk menyederhanakan kode, kita akan melakukannya tanpanya. Sudah waktunya untuk pola Pabrik Abstrak. Kami punya biksu, sekarang kami bisa membuatkan mereka pakaian, rosario, dan lain-lain. Mari kita mulai dengan pakaian, yaitu jika kita kembali ke definisi awal, pakaian akan menjadi sekumpulan benda yang saling berhubungan atau saling bergantung . Mari kita mulai dengan permasalahan bahwa setiap jenis bhikkhu memiliki jubah yang berbeda. Jika kita juga menambahkan Buddhis, maka keduanya akan sangat berbeda :) Untuk melakukan ini, kita dapat membuat antarmuka pabrik, yang implementasinya akan membuat pakaian yang diperlukan. Oleh karena itu A) Kami membuat pabrik pembuatan pakaian
public interface MonkFactory {
    Clothing createClothing();
}
dan implementasinya
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();
    }
}
Baiklah, jangan lupakan para biksu Buddha :)
public class BuddhistMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new BuddhistClothing();
    }
}
B) Membuat kelas pakaian (untuk menyederhanakan, mari kita ambil elemen kunci dari pakaian biksu, kami tidak akan membahasnya secara detail):
public abstract class Clothing {
    private String name;

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

    public String getName() {
        return name;
    }
}
dan kelas anak
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) Selanjutnya kita mengubah kelas para bhikkhu sehingga mereka memiliki 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 berisi metode Pabrik 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);
}
implementasi 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) Periksa hasilnya:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Pabrik pembuat pakaian sudah mulai bekerja dengan baik. Sekarang Anda dapat menambahkan ke pabrik produksi peralatan untuk para biksu agar doa berhasil (rosario, dll.). Namun pertanyaannya masih tetap, apakah mungkin menggunakan 2 pola secara bersamaan? Tentu saja bisa :) Mari kita coba membuat versi final proyek kita dan menambahkan biksu Hindu: A) Pabrik sekarang membuat suara biksu seperti “pabrik 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 + implementasi nyata dari kelas Biara tidak diperlukan, mereka dilaksanakan oleh pabrik (sebaliknya, kita bisa meninggalkannya dan menghapus pabrik, tetapi pada dasarnya mereka akan menjadi bukan pabrik, hanya di dalam hal ini Biara harus dijadikan antarmuka, 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) Para bhikkhu sekarang mengandung
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);
}
berisi metode pabrik dalam implementasi, yang diimplementasikan menggunakan pabrik:
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 periksa:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
Kesimpulannya, Anda dapat mencatat bahwa metode Pabrik menggunakan kelas abstrak dengan metode yang tidak diterapkan, yang diimplementasikan dalam subkelas, dan Pabrik Abstrak menggunakan antarmuka, di mana implementasi (dalam kasus kami, pembuatan biksu) terjadi di kelas yang mengimplementasikan antarmuka ini.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION