Kitabda “Əvvəlcə baş. Design Patterns” bu nümunələri aşağıdakı kimi müəyyən edir: Fabrika metodu nümunəsi obyekt yaratmaq üçün interfeysi müəyyən edir, lakin alt siniflərə yaradılacaq nümunənin sinfini seçməyə imkan verir. Beləliklə, Fabrika metodu instantasiya əməliyyatını alt siniflərə həvalə edir. Abstract Factory nümunəsi konkret siniflərini göstərmədən bir-biri ilə əlaqəli və ya bir-birindən asılı olan obyektlərin ailələrini yaratmaq üçün interfeys təqdim edir. Bunu daha ətraflı anlamağa çalışaq. Tutaq ki, siz... (burada orijinal və qeyri-adi bir şeyə ehtiyacınız var) rahib olmağa qərar verən insanlar haqqında bir oyun yazmağa qərar verdiniz. Aşağıdakılardan başlaya bilərik. 1) Monk sinfi və uşaq sinifləri yaradın (əvvəlcə birini yaradaq):
public abstract class Monk {

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я православный монах");
    }
}
2) Və əlbəttə ki, "monastır andlarını" həyata keçirə biləcəyiniz bir Monastır sinfi yaradın:
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;
    }
}
Yaxşı, nəticəni yoxlayaq:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new Monastery();
        monastery.createMonk("ORTODOX");
        monastery.getMonk().description();
    }
}
Я православный монах
İndi... bir katolik rahib yaratmaq lazımdırsa, sizə lazım olacaq A) Katolik rahib üçün yeni sinif yaradın:
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
B) Monastır sinfində dəyişikliklər etmək:
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;
    }
}
və buna görə də hər dəfə yeni rahib növləri təqdim olunanda siz yeni sinif yaratmalı və mövcud olanı redaktə etməli olacaqsınız. Bu vəziyyətdə, monastır sinifimizi dəyişikliklərdən bir şəkildə "kapsullaşdırmaq" üçün nə edilə bilər. Zavod metodu nümunəsindən istifadə etməyə cəhd edə bilərsiniz. Necə görünəcək A) Gəlin rahib sinfini olduğu kimi tərk edək, istisna olmaqla, bir Anqlikan rahibini əlavə edək (yalnız katoliklərdə və pravoslav xristianlarda monastizm yoxdur):
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) Monastır sinfini aşağıdakı kimi dəyişdirək (onu və metodunu abstrakt edək). Burada sadəcə Fabrika metodundan istifadə edirik :
public abstract class Monastery {
    protected abstract Monk createMonk();
}
və metodun tətbiqi ilə uşaq sinifləri yaradın:
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) Kodu yoxlayaq
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();
    }
}
Я православный монах
Я католический монах
Я англиканский монах
Bunlar. indi gördüyümüz kimi, yeni növ rahiblər əlavə edərkən, mövcud sinifləri dəyişdirməyə ehtiyac olmayacaq, ancaq zəruri hallarda yenilərini əlavə edin (müəyyən bir monastır və rahib sinfi). Ola bilsin ki, kimsə Monk sinfində əvvəldən mövcud olan təsvir metodunun da Fabrika olduğunun fərqinə varıb :) Zavod metodunun tərifi deyirdi ki, nümunəmiz obyekt yaratmaq üçün interfeysi müəyyənləşdirir, lakin biz heç bir şey yaratmamışıq. interfeyslər, baxmayaraq ki, biz Monastery sinifini bir interfeys kimi yarada və onu xüsusi tətbiqlərdə həyata keçirə bildik. Bu, daha geniş mənada “interfeys” sözünə aiddir. Tərif həmçinin dedi ki, bu, alt siniflərə yaratdıqları nümunənin sinfini seçməyə imkan verir . Burada sadəcə görürük ki, alt siniflər (uşaq siniflər) bu üsulu həyata keçirir (yəni rahib obyektləri yaratmaq üçün bu səlahiyyətlər onlara verilir). İndi proqramımızı bir az da genişləndirək, bu və ya digər məzhəbdə müxtəlif rahiblərin olması ehtimalını təqdim edək. Məsələn, Pravoslavlıqda Pravoslav Kilsəsinin monastırlar və monastırlarla bağlı mövqeyinə əsaslanaraq (Rus Pravoslav Kilsəsinin Yepiskoplar Şurasında 29 noyabr - 2 dekabr 2017-ci il tarixlərində qəbul edilmişdir) belə nəticəyə gələ bilərik ki, 2 növ rahib var. : - Kiçik sxem (mantiya). - Sxema (böyük sxem). "Hazırlıq mərhələləri" də var, lakin insanlar rahib hesab edilmir (Trudnik, Acemi və Ryasofor və ya Rahib), çünki onlar monastır and içmirlər. Ona görə də biz bunları nəzərə almırıq. Bu halda nə əldə edirik: A) Fabrik üsulu ilə monastır sinfi (sadələşdirmək üçün indilik pravoslav monastizminə diqqət yetirək) :
public abstract class Monastery {
    protected abstract Monk createMonk(String type);
}
və xüsusi bir monastır
public class OrthodoxMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new OrthodoxMonk(type);
    }
}
B) Rahib sinfini düzəldək:
public abstract class Monk {
    String kind;

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

    public abstract void description();
}
və uşaq sinfi:
public class OrthodoxMonk extends Monk {
    public OrthodoxMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
    }
}
C) Gəlin kodumuzu yoxlayaq:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
Beləliklə, Fabrika Metodu nümunəsindən istifadə edərək, biz əvvəllər yazılmış sinifləri dəyişdirməyinizə nail olduq, lakin rahiblərin şəkillərini (növlərini) genişləndirərkən kodda minimum dəyişikliklər tələb olunur. Katolik rahiblərinin bütün əmrlərini və yığıncaqlarını yoxlayaq və əlavə edək :) Ancaq ən məşhur 3-ə diqqət yetirmək daha yaxşıdır, çünki onlardan 100-dən çoxu var: 1) Benediktin 2) Cezuit 3) Fransiskan Bunu etmək üçün əvvəllər olduğu kimi pravoslav rahib, biz katolik rahibinin müəyyən bir sinfini həyata keçirməliyik:
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

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

    @Override
    protected Monk createMonk(String type) {
        return new CatholicMonk(type);
    }
}
və kodu yoxlayın:
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();
    }
}
Я православный монах - Мантийный монах
Я православный монах - Великосхимник
Я католический монах - Бенедиктинец
Я католический монах - Иезуит
Я католический монах - Францисканец
Bu nümunə ilə bitirək. Bütün bu növ rahibləri də əvvəlcədən E-num sinfinə əlavə etmək olar, lakin kodu sadələşdirmək üçün biz onsuz edəcəyik. Abstrakt Fabrika nümunəsinin vaxtı gəldi. Rahiblərimiz var, indi onlara paltar, təsbeh və s. tikə bilərdik. Geyimdən başlayaq, yəni başlanğıcda tərifimizə qayıtsaq, geyim bir-biri ilə əlaqəli və ya bir-birindən asılı olan obyektlər ailəsinə çevriləcəkdir . Problemdən başlayaq ki, hər bir rahib növünün fərqli paltarları var. Buddist əlavə etsək, onda onlar tamamilə fərqli olacaqlar :) Bunun üçün biz zavod interfeysi yarada bilərik, onun həyata keçirilməsi lazımi paltarları yarada bilər. Buna görə də A) Paltar tikmək üçün fabrik yaradırıq
public interface MonkFactory {
    Clothing createClothing();
}
və onun həyata keçirilməsi
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();
    }
}
Buddist rahibləri də unutmayaq :)
public class BuddhistMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new BuddhistClothing();
    }
}
B) Geyim sinfi yaradın (sadələşdirmək üçün rahiblərin geyiminin əsas elementini götürək, təfərrüata girməyəcəyik):
public abstract class Clothing {
    private String name;

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

    public String getName() {
        return name;
    }
}
və uşaq sinifləri
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) Sonra rahiblərin siniflərini dəyişdiririk ki, paltarları olsun:
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) Monastır sinfi bizim Fabrika metodumuzu ehtiva edir
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);
}
tətbiqlərimiz dəyişməyib
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) Nəticəni yoxlayın:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Paltar tikən fabrik yaxşı işləməyə başlayıb. İndi fabrikə uğurlu dua üçün rahiblər üçün avadanlıq istehsalını əlavə edə bilərsiniz (təsbeh muncuqları və s.). Ancaq sual hələ də qalır: 2 nümunəni birlikdə istifadə etmək mümkündürmü? Əlbəttə edə bilərsiniz :) Gəlin layihəmizin son versiyasını hazırlamağa və hindu rahibini əlavə etməyə çalışaq: A) İndi fabriklər rahiblər yaradırlar “ulduz fabriki” kimi səslənir :
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) Monastır sinfi + Monastır sinfinin konkret tətbiqləri lazım deyil, onları fabrik həyata keçirir (əksinə, biz onları tərk edib fabrikləri çıxara bilərdik, amma mahiyyət etibarilə onlar sadəcə olaraq fabriklərin əvəzinə olacaqlar, yalnız bu halda monastır mücərrəd sinif deyil, interfeys olmalıdır). Və tətbiq sinfini əlavə edin:
public class Application {

    public Monk create(MonkFactory monkFactory, String type) {
        Monk monk = monkFactory.createMonk(type);
        monk.prepare(monkFactory);
        return monk;
    }
}
B) Rahiblər indi ehtiva edir
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);
}
Fabrikdən istifadə edərək həyata keçirilən tətbiqlərdə zavod metodunu ehtiva edir:
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) Və yoxlayaq:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
Sonda qeyd edə bilərsiniz ki, Fabrika Metodunda yarımsiniflərdə həyata keçirilən icra olunmamış metodu olan mücərrəd sinifdən, Abstrakt Fabrika isə interfeysdən istifadə edib, burada tətbiqetmə (bizim vəziyyətimizdə rahib yaratmaq) bunu həyata keçirən siniflərdə baş verib. interfeys.