JavaRush /Java блогы /Random-KK /Дизайн үлгілері: FactoryMethod

Дизайн үлгілері: FactoryMethod

Топта жарияланған
Сәлеметсіз бе! Бүгін біз дизайн үлгілерін зерттеуді жалғастырамыз және зауыттық әдіс (FactoryMethod) туралы сөйлесеміз. Дизайн үлгілері: FactoryMethod - 1Сіз бұл үлгінің не екенін және қандай тапсырмалар үшін қолайлы екенін білесіз. Біз бұл дизайн үлгісін тәжірибеде қарастырамыз және оның құрылымын зерттейміз. Жоғарыда айтылғандардың барлығы сізге түсінікті болу үшін келесі тақырыптарды түсінуіңіз керек:
  1. Java тіліндегі мұра.
  2. Java тіліндегі дерексіз әдістер мен класстар.

Зауыттық әдіс қандай мәселені шешеді?

Барлық зауыттық дизайн үлгілерінде қатысушылардың екі тобы бар - жасаушылар (зауыттардың өздері) және өнімдер (зауыттар жасаған an objectілер). Жағдайды елестетіп көріңіз: бізде AutoRush брендімен автомобильдер шығаратын зауыт бар. Ол дененің әртүрлі типтері бар автомобиль үлгілерін жасауды біледі:
  • седандар
  • станциялық вагондар
  • купе
Біз үшін бәрі жақсы болғаны сонша, бір күні біз OneAuto концернін сіңіріп алдық. Саналы менеджерлер ретінде біз OneAuto тұтынушыларын жоғалтқымыз келмейді және біздің міндетіміз мыналарды шығара алатындай етіп өндірісті қайта құрылымдау болып табылады:
  • AutoRush седандары
  • AutoRush станциялық вагондары
  • купе AutoRush
  • OneAuto седандары
  • OneAuto станциялық вагондары
  • OneAuto купе
Көріп отырғаныңыздай, туынды өнімдердің бір тобының орнына кейбір бөлшектермен ерекшеленетін екеуі пайда болды. Зауыттық әдісті жобалау үлгісі әрқайсысының белгілі бір ерекшелігі бар өнімдердің әртүрлі топтарын құру мәселесін шешеді. Біз бұл үлгінің принципін тәжірибеде қарастырамыз, бірте-бірте қарапайымнан күрделіге қарай, алдыңғы лекциялардың бірінде жасаған кофеханамыздың мысалын қолданамыз .

Зауыттық үлгі туралы аздап

Еске сала кетейін: біз сіздермен шағын виртуалды кофехана салдық. Онда біз қарапайым зауыттың көмегімен кофенің әртүрлі түрлерін жасауды үйрендік. Бүгін біз бұл мысалды нақтылайтын боламыз. Қарапайым фабрикасы бар кофеханамыздың қандай болғанын еске түсірейік. Бізде кофе сабағы болды:
public class Coffee {
    public void grindCoffee(){
        // перемалываем кофе
    }
    public void makeCoffee(){
        // делаем кофе
    }
    public void pourIntoCup(){
        // наливаем в чашку
    }
}
Сондай-ақ оның бірнеше мұрагерлері - біздің зауыт шығара алатын кофенің ерекше түрлері:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Тапсырысты қабылдау ыңғайлы болу үшін біз аударымдарды енгіздік:
public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}
Кофе фабрикасының өзі мынадай болды:
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;
    }
}
Ақырында, кофехананың өзі:
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;
    }
}

Қарапайым зауытты жаңғырту

Біздің кофехананың жұмысы жақсы. Біз кеңейтуді ойластырғанымыз сонша. Біз бірнеше жаңа пункттер ашқымыз келеді. Іскер жігіттер ретінде біз монотонды кофеханаларды құртпаймыз. Әрқайсысының өзіндік иірімдері болғанын қалаймын. Сондықтан, бастау үшін біз екі нүктені ашамыз: итальяндық және американдық стильде. Өзгерістер интерьерге ғана емес, сонымен қатар сусындарға да әсер етеді:
  • итальяндық кофеханада біз арнайы ұнтақтау және қуыру арқылы тек итальяндық кофе брендтерін қолданамыз.
  • Американдық бөлік сәл үлкенірек болады және әрбір тапсырыспен біз балқытылған зефир - зефирге қызмет етеміз.
Өзгеріссіз қалатын жалғыз нәрсе - бұл өзін жақсы дәлелдеген біздің бизнес-модель. Егер code тілінде сөйлейтін болсақ, осылай болады. Бізде өнімнің 4 класы болды:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Және ол 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 {}
Біз ағымдағы бизнес үлгісін өзгеріссіз қалдырғымыз келетіндіктен, әдіс orderCoffee(CoffeeType type)ең аз өзгерістерге ұшырағанын қалаймыз. Оны қарастырайық:
public Coffee orderCoffee(CoffeeType type) {
    Coffee coffee = coffeeFactory.createCoffee(type);
    coffee.grindCoffee();
    coffee.makeCoffee();
    coffee.pourIntoCup();

    System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
    return coffee;
}
Бізде қандай нұсқалар бар? Біз зауытты қалай жазу керектігін білеміз, солай ма? Бірден ойға келетін қарапайым нәрсе - екі ұқсас зауытты жазу, содан кейін конструктордағы кофеханаға қажетті енгізуді беру. Сонда кофехананың класы өзгермейді. Біріншіден, біз жаңа зауыт сыныбын жасап, қарапайым зауытымыздан мұра алып createCoffee (CoffeeType type), . Итальяндық және американдық стильде кофе жасайтын фабрикаларды жазайық:
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;
    }

}
Енді біз CoffeeShop-қа қажетті зауыттық енгізуді тапсыра аламыз. Әртүрлі кофеханалардан кофеге тапсырыс беру codeы қандай болатынын көрейік. Мысалы, итальяндық және американдық стильдегі капучино:
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);
    }
}
Біз екі түрлі кофехана құрдық, әрқайсысын қажетті зауытқа ауыстырдық. Бір жағынан мақсатымызға жеттік, екінші жағынан... Кәсіпкердің жанын тырнап жатқан бірдеңе... Ненің кемшілігі бар екенін анықтайық. Біріншіден, зауыттардың көптігі. Әр уақытта жаңа нүкте үшін өз зауытыңызды құруға болады ма, сонымен қатар кофехананы құру кезінде қажетті зауыт конструкторға берілетініне көз жеткізуге болады ма? Екіншіден, бұл әлі қарапайым зауыт. Аздап модернизацияланған. Біз мұнда әлі де жаңа үлгіні зерттеп жатырмыз. Үшіншіден, мұны басқаша жасауға болады емес пе? Сынып ішінде кофе дайындауға қатысты барлық сұрақтарды локализациялау CoffeeShop, кофе жасау және тапсырысқа қызмет көрсету процестерін байланыстыру, бірақ сонымен бірге әртүрлі стильде кофе жасау үшін жеткілікті икемділікті сақтай алсақ, жақсы болар еді. Жауап иә, сіз аласыз. Бұл зауыттық әдісті жобалау үлгісі деп аталады.

Қарапайым зауыттан зауыттық әдіске дейін

Мәселені мүмкіндігінше тиімді шешу үшін біз:
  1. createCoffee(CoffeeType type)Әдісті сыныпқа қайтарайық CoffeeShop.
  2. Бұл әдісті дерексіз етіп көрсетейік.
  3. Сыныптың өзі CoffeeShopабстрактілі болады.
  4. Сыныптың CoffeeShopмұрагерлері болады.
Иә, досым. Итальяндық кофехана - бұл итальяндық баристалардың ең жақсы дәстүрлеріне сәйкес CoffeeShopәдісті жүзеге асыратын класс мұрагері . createCoffee(CoffeeType type)Сонымен, тәртіппен. 1-қадам.Сыныпты рефератқа айналдырайық Coffee. Қазір бізде әртүрлі өнімдердің екі отбасы бар. Итальяндық және американдық кофе сусындарының әлі күнге дейін ортақ ата-бабасы бар: Coffee. Оны дерексіз ету дұрыс болар еді:
public abstract class Coffee {
    public void makeCoffee(){
        // делаем кофе
    }
    public void pourIntoCup(){
        // наливаем в чашку
    }
}
CoffeeShop2-қадам. Абстрактілі әдіспен, дерексіз етіп жасаңызcreateCoffee(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);
}
3-қадам. Абстрактілі кофехананың ұрпағы болып табылатын итальяндық кофехана жасаңыз. Онда біз createCoffee(CoffeeType type)итальяндық ерекшеліктерді ескере отырып әдісті жүзеге асырамыз.
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;
    }
}
4-қадам. Американдық үлгідегі кофехана үшін де солай істейік.
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;
    }
}
5-қадам. Американдық және итальяндық стильдегі латтеге тапсырыс беру қандай болатынын қарастырайық:
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);
    }
}
Құттықтаймын. Біз кофеханада зауыттық дизайн үлгісін жаңа ғана енгіздік.

Зауыттық әдіс қалай жұмыс істейді

Енді не алғанымызды егжей-тегжейлі қарастырайық. Төмендегі диаграмма нәтижесінде алынған сыныптар көрсетілген. Жасыл блоктар - жасаушы сыныптары, көк блоктар - өнім сыныптары. Дизайн үлгілері: FactoryMethod - 2Қандай қорытынды жасауға болады?
  1. Барлық өнімдер абстрактілі класстың жүзеге асырылуы болып табылады Coffee.
  2. Барлық жасаушылар абстрактілі класстың іске асырылуы болып табылады CoffeeShop.
  3. Біз екі параллель класс иерархиясын байқаймыз:
    • Өнімдер иерархиясы. Біз итальяндық ұрпақтарды және американдық ұрпақтарды көреміз
    • Жасаушылар иерархиясы. Біз итальяндық ұрпақтарды және американдық ұрпақтарды көреміз
  4. Суперсыныпта қандай нақты өнімді іске асыру ( ) жасалатыны CoffeeShopтуралы ақпарат жоқ .Coffee
  5. Суперкласс CoffeeShopбелгілі бір өнімді жасауды ұрпақтарына тапсырады.
  6. Әрбір ұрпақ класы өзінің ерекшелігіне сәйкес CoffeeShopзауыттық әдісті жүзеге асырады . createCoffee()Басқаша айтқанда, жасаушылар кластарын іске асыру шеңберінде жасаушылар класының ерекшеліктеріне негізделген нақты өнімді дайындау туралы шешім қабылданады.
Енді сіз зауыттық әдіс үлгісін анықтауға дайынсыз . Зауыттық әдіс үлгісі нысанды жасау үшін интерфейсті анықтайды, бірақ ішкі сыныптарға жасалатын дананың сыныбын таңдауға мүмкіндік береді. Осылайша, Factory әдісі даналық әрекетті ішкі сыныптарға береді. Жалпы алғанда, анықтаманы есте сақтау заттардың қалай жұмыс істейтінін түсіну сияқты маңызды емес.

Зауыттық әдіс құрылымы

Дизайн үлгілері: FactoryMethod - 3Жоғарыдағы диаграмма зауыттық әдіс үлгісінің жалпы құрылымын көрсетеді. Мұнда тағы не маңызды?
  1. Creator сыныбы зауыттық әдісті қоспағанда, өнімдермен әрекеттесетін барлық әдістерді іске асыруды қамтиды.
  2. Абстрактілі әдісті factoryMethod()сыныптың барлық ұрпақтары жүзеге асыруы керек Creator.
  3. Класс өнімді тікелей шығаратын ConcreteCreatorәдісті жүзеге асырады .factoryMethod()
  4. Бұл сынып нақты өнімдерді жасауға жауап береді. Бұл өнімдерді жасау туралы ақпараты бар жалғыз сынып.
  5. Барлық өнімдер ортақ интерфейсті жүзеге асыруы керек - жалпы өнім класының ұрпақтары болуы керек. Бұл өнімдерді пайдаланатын сыныптар оларда нақты іске асырудан гөрі абстракциялар деңгейінде жұмыс істей алуы үшін қажет.

Үй жұмысы

Сонымен, бүгін біз көп жұмыс жасадық және зауыттық әдісті жобалау үлгісін зерттедік. Өтілген материалды біріктіретін уақыт келді! 1-тапсырма. Басқа кофехана ашу бойынша жұмыс. Ол ағылшын стилінде немесе испан тілінде жасалуы мүмкін. Немесе тіпті ғарыш кемесінің стилінде. Кофеге жылтырату үшін тағамдық бояуды қосайық, жалпы алғанда, кофе жай ғана кеңістік болады! Тапсырма 2. Соңғы дәрісте виртуалды суши-бар немесе виртуалды пиццерия жасау міндеті тұрды. Сіздің міндетіңіз - бір орында тұрмау. Бүгін сіз жетістікке жету үшін зауыттық әдіс үлгісін қалай қолдануға болатынын білдіңіз. Бұл білімді пайдаланып, өз бизнесіңізді кеңейтетін кез келді;)
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION