JavaRush /Java Blogu /Random-AZ /Dizayn nümunələri: Fabrika metodu

Dizayn nümunələri: Fabrika metodu

Qrupda dərc edilmişdir
Salam! Bu gün biz dizayn nümunələrini öyrənməyə və zavod üsulu (FactoryMethod) haqqında danışmağa davam edəcəyik. Dizayn nümunələri: Fabrika metodu - 1Bunun nə olduğunu və bu şablonun hansı vəzifələrə uyğun olduğunu öyrənəcəksiniz. Biz bu dizayn nümunəsinə praktikada baxacağıq və onun strukturunu araşdıracağıq. Yuxarıda göstərilənlərin hamısını sizə aydınlaşdırmaq üçün aşağıdakı mövzuları başa düşməlisiniz:
  1. Java-da miras.
  2. Java-da abstrakt metodlar və siniflər.

Zavod üsulu hansı problemi həll edir?

Bütün fabrik dizayn nümunələrində iki iştirakçı qrupu var - yaradıcılar (fabriklərin özləri) və məhsullar (fabriklərin yaratdığı obyektlər). Vəziyyəti təsəvvür edin: bizdə AutoRush brendi altında avtomobillər istehsal edən zavodumuz var. O, müxtəlif bədən tipli avtomobil modellərini necə yaratmağı bilir:
  • sedanlar
  • stansiya vaqonları
  • kupe
İşlərimiz o qədər yaxşı gedirdi ki, bir gün OneAuto konsernini udduq. Ağıllı menecerlər olaraq, biz OneAuto müştərilərini itirmək istəmirik və bizim vəzifəmiz istehsalı istehsal edə biləcəyimiz şəkildə yenidən qurmaqdır:
  • AutoRush sedanları
  • AutoRush stansiya vaqonları
  • kupe AutoRush
  • OneAuto sedanları
  • OneAuto stansiya vaqonları
  • OneAuto kupe
Gördüyünüz kimi, bir qrup törəmə məhsulun əvəzinə bəzi detallarda fərqlənən ikisi meydana çıxdı. Zavod üsulu dizayn nümunəsi hər biri müəyyən xüsusiyyətlərə malik olan müxtəlif məhsul qruplarının yaradılması problemini həll edir. Əvvəlki mühazirələrdən birində yaratdığımız qəhvəxana nümunəmizdən istifadə edərək, sadədən mürəkkəbə tədricən keçərək bu şablonun prinsipini praktikada nəzərdən keçirəcəyik .

Zavod şablonu haqqında bir az

Xatırladım: sizinlə kiçik bir virtual qəhvəxana tikdik. Orada biz sadə bir fabrikdən istifadə edərək müxtəlif növ qəhvə yaratmağı öyrəndik. Bu gün biz bu nümunəni təkmilləşdirəcəyik. Sadə bir fabrik olan qəhvəxanamızın necə göründüyünü xatırlayaq. Qəhvə dərsimiz var idi:
public class Coffee {
    public void grindCoffee(){
        // перемалываем кофе
    }
    public void makeCoffee(){
        // делаем кофе
    }
    public void pourIntoCup(){
        // наливаем в чашку
    }
}
Həm də onun bir neçə varisləri - fabrikimizin istehsal edə biləcəyi xüsusi qəhvə növləri:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Sifarişlərin qəbulunun rahatlığı üçün biz köçürmələri tətbiq etdik:
public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}
Qəhvə fabrikinin özü belə görünürdü:
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;
    }
}
Və nəhayət, qəhvəxananın özü:
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;
    }
}

Sadə bir fabrikin modernləşdirilməsi

Qəhvəxanamız yaxşı işləyir. O qədər ki, genişləndirməyi düşünürük. Biz bir neçə yeni nöqtə açmaq istəyirik. Təşəbbüskar uşaqlar olaraq, biz monoton qəhvəxanaları ləğv etməyəcəyik. İstəyirəm ki, hər birinin özünəməxsus twistləri olsun. Buna görə də, başlamaq üçün iki nöqtə açacağıq: İtalyan və Amerika üslublarında. Dəyişikliklər təkcə interyerə deyil, həm də içkilərə təsir edəcək:
  • İtalyan qəhvə mağazasında biz xüsusi üyüdülmə və qovurma ilə yalnız italyan qəhvə markalarından istifadə edəcəyik.
  • Amerika hissəsi bir az daha böyük olacaq və hər sifarişlə ərinmiş marshmallows - marshmallows təqdim edəcəyik.
Dəyişmədən qalacaq yeganə şey özünü yaxşı tərəfdən sübut etmiş biznes modelimizdir. Əgər kod dilində danışsaq, belə olur. 4 növ məhsulumuz var idi:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Və 8 olur:
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 {}
Mövcud biznes modelini dəyişməz saxlamaq istədiyimiz üçün metodun orderCoffee(CoffeeType type)minimum sayda dəyişikliyə məruz qalmasını istəyirik. Gəlin buna nəzər salaq:
public Coffee orderCoffee(CoffeeType type) {
    Coffee coffee = coffeeFactory.createCoffee(type);
    coffee.grindCoffee();
    coffee.makeCoffee();
    coffee.pourIntoCup();

    System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
    return coffee;
}
Hansı variantlarımız var? Biz artıq fabrik yazmağı bilirik, elə deyilmi? Dərhal ağlına gələn ən sadə şey, iki oxşar fabrik yazmaq və sonra lazım olan tətbiqi konstruktordakı qəhvə mağazamıza ötürməkdir. Onda qəhvəxananın sinfi dəyişməyəcək. Əvvəlcə yeni fabrik sinfi yaratmalı, sadə fabrikimizdən miras almalı və createCoffee (CoffeeType type). İtalyan və Amerika üslubunda qəhvə yaratmaq üçün fabrikləri yazaq:
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;
    }

}
İndi biz lazımi zavod tətbiqini CoffeeShop-a ötürə bilərik. Gəlin görək müxtəlif qəhvəxanalardan qəhvə sifariş etmək kodu necə olacaq. Məsələn, İtalyan və Amerika üslubunda kapuçino:
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);
    }
}
Biz iki fərqli qəhvəxana yaratdıq, hər birini lazımi fabrikə köçürdük. Bir tərəfdən məqsədimizə çatdıq, digər tərəfdən... Sahibkarın qarşısıalınmaz ruhunu cızırdayan nə isə... Nəyin səhv olduğunu anlayaq. Birincisi, fabriklərin bolluğu. Hər dəfə yeni bir nöqtə üçün öz fabrikinizi yaratmaq və əlavə olaraq qəhvəxana yaradan zaman tələb olunan fabrikin konstruktora ötürüldüyünə əmin olmaq mümkündürmü? İkincisi, hələ də sadə bir fabrikdir. Sadəcə bir az modernləşdirilib. Biz burada hələ də yeni nümunəni öyrənirik. Üçüncüsü, bunu başqa cür etmək mümkün deyilmi? Sinif otağında qəhvə hazırlamaqla bağlı bütün sualları lokallaşdıra bilsək CoffeeShop, qəhvə yaratmaq və sifarişə xidmət göstərmək proseslərini əlaqələndirə bilsək, eyni zamanda müxtəlif üslublarda qəhvə hazırlamaq üçün kifayət qədər çevikliyi qoruyub saxlaya bilsək çox gözəl olardı. Cavab bəli, edə bilərsiniz. Buna zavod metodu dizayn nümunəsi deyilir.

Sadə bir fabrikdən zavod üsuluna

Problemi mümkün qədər səmərəli həll etmək üçün biz:
  1. Gəlin metodu createCoffee(CoffeeType type)sinfə qaytaraq CoffeeShop.
  2. Gəlin bu metodu mücərrəd edək.
  3. Sinfin özü CoffeeShopmücərrəd olacaq.
  4. Sinfin CoffeeShopvarisləri olacaq.
Bəli, dostum. İtalyan qəhvəxanası italyan baristalarının ən yaxşı ənənələrinə uyğun CoffeeShopmetodu həyata keçirən sinfin varisindən başqa bir şey deyil . createCoffee(CoffeeType type)Beləliklə, qaydada. Addım 1. Gəlin sinfi Coffeemücərrəd edək. İndi fərqli məhsullardan ibarət iki ailəmiz var. İtalyan və Amerika qəhvə içkilərinin hələ də ortaq əcdadı var: Coffee. Bunu mücərrəd etmək düzgün olardı:
public abstract class Coffee {
    public void makeCoffee(){
        // делаем кофе
    }
    public void pourIntoCup(){
        // наливаем в чашку
    }
}
Addım 2. CoffeeShopMücərrəd üsulla onu abstrakt edincreateCoffee(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);
}
Addım 3. Mücərrəd qəhvəxananın nəslindən olan italyan qəhvəxanası yaradın. Burada createCoffee(CoffeeType type)italyan xüsusiyyətlərini nəzərə alaraq üsulu həyata keçiririk.
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;
    }
}
Addım 4. Amerika tipli qəhvəxana üçün də eyni şeyi edək.
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;
    }
}
Addım 5. Gəlin Amerika və İtalyan üslubunda latte sifariş etməyin necə olacağına nəzər salaq:
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);
    }
}
Təbrik edirik. Qəhvəxanamızda fabrik üsulu ilə dizayn nümunəsini təzəcə tətbiq etdik.

Zavod üsulu necə işləyir

İndi əldə etdiklərimizə daha yaxından nəzər salaq. Aşağıdakı diaqram nəticədə sinifləri göstərir. Yaşıl bloklar yaradıcı siniflər, mavi bloklar məhsul sinifləridir. Dizayn nümunələri: Fabrika metodu - 2Hansı nəticələr çıxarmaq olar?
  1. Bütün məhsullar mücərrəd sinfin tətbiqləridir Coffee.
  2. Bütün yaradıcılar mücərrəd sinfin tətbiqləridir CoffeeShop.
  3. İki paralel sinif iyerarxiyasını müşahidə edirik:
    • Məhsulların iyerarxiyası. Biz İtalyan nəslini və Amerika nəslini görürük
    • Yaradıcıların iyerarxiyası. Biz İtalyan nəslini və Amerika nəslini görürük
  4. Supersinfdə hansı xüsusi məhsul tətbiqinin ( ) yaradılacağı CoffeeShopbarədə məlumat yoxdur .Coffee
  5. Supersinif CoffeeShopmüəyyən bir məhsulun yaradılmasını öz nəslinə həvalə edir.
  6. Hər bir nəsil sinfi öz xüsusiyyətlərinə uyğun olaraq CoffeeShopzavod metodunu həyata keçirir . createCoffee()Başqa sözlə, yaradıcı siniflərin həyata keçirilməsi çərçivəsində yaradıcı sinifin xüsusiyyətlərinə əsaslanaraq konkret məhsulun hazırlanması barədə qərar qəbul edilir.
İndi siz zavod metodu modelini təyin etməyə hazırsınız . Zavod metodu nümunəsi obyekt yaratmaq üçün interfeysi müəyyənləşdirir, 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. Ümumiyyətlə, tərifi xatırlamaq işlərin necə işlədiyini anlamaq qədər vacib deyil.

Zavod metodunun quruluşu

Dizayn nümunələri: Fabrika metodu - 3Yuxarıdakı diaqram zavod metodunun nümunəsinin ümumi quruluşunu göstərir. Burada başqa nə vacibdir?
  1. Creator sinfi zavod metodu istisna olmaqla, məhsullarla qarşılıqlı əlaqədə olan bütün metodların tətbiqlərini ehtiva edir.
  2. Mücərrəd metod factoryMethod()sinfin bütün nəsilləri tərəfindən həyata keçirilməlidir Creator.
  3. Sinif birbaşa məhsul istehsal edən ConcreteCreatormetodu həyata keçirir .factoryMethod()
  4. Bu sinif xüsusi məhsulların yaradılmasına cavabdehdir. Bu, bu məhsulların yaradılması haqqında məlumatı olan yeganə sinifdir.
  5. Bütün məhsullar ümumi interfeys tətbiq etməlidir - ümumi məhsul sinifinin nəslindən olmalıdır. Bu, məhsullardan istifadə edən siniflərin konkret tətbiqlərdən daha çox abstraksiyalar səviyyəsində fəaliyyət göstərə bilməsi üçün lazımdır.

Ev tapşırığı

Beləliklə, bu gün biz kifayət qədər çox iş gördük və zavod üsulu ilə dizayn nümunəsini öyrəndik. Əhatə etdiyiniz materialı birləşdirmək vaxtıdır! Tapşırıq 1. Başqa bir qəhvəxana açmaq üzərində işləyin. İngilis üslubunda və ya ispan dilində hazırlana bilər. Və ya hətta bir kosmik gəmi üslubunda. Qəhvəni parlaq etmək üçün ona qida boyası əlavə edək və ümumiyyətlə, qəhvə sadəcə boşluq olacaq! Tapşırıq 2. Son mühazirədə sizin qarşınızda virtual suşi barı və ya virtual pizzacı yaratmaq tapşırığı var idi. Sizin vəzifəniz yerində durmamaqdır. Bu gün siz uğur əldə etmək üçün zavod metodundan necə istifadə edə biləcəyinizi öyrəndiniz. Bu biliklərdən yararlanmağın və öz biznesinizi genişləndirməyin vaxtıdır ;)
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION