JavaRush /Java блогу /Random-KY /Дизайн үлгүлөрү: FactoryMethod

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

Группада жарыяланган
Салам! Бүгүн биз дизайн үлгүлөрүн изилдөөнү улантабыз жана фабрикалык ыкма (FactoryMethod) жөнүндө сүйлөшөбүз. Дизайн үлгүлөрү: FactoryMethod - 1Бул эмне экенин жана бул шаблон кандай тапшырмаларга ылайыктуу экенин билесиз. Биз бул дизайн үлгүсүн иш жүзүндө карап, анын түзүлүшүн изилдейбиз. Жогоруда айтылгандардын бардыгы сизге түшүнүктүү болушу үчүн, сиз төмөнкү темаларды түшүнүшүңүз керек:
  1. Javaдагы мурас.
  2. Java тorндеги абстракттуу методдор жана класстар.

Заводдук ыкма кандай маселени чечет?

Бардык фабрикалык дизайн моделдеринде катышуучулардын эки тобу бар - жаратуучулар (фабрикалардын өздөрү) жана буюмдар (заводдор тарабынан түзүлгөн 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 тorнде сүйлөсөк, бул эмне болот. Бизде продукциянын 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);
    }
}
Биз эки башка кафе түзүп, ар бирин керектүү заводго өткөрүп бердик. Бир чети максатыбызга жеттик, экинчи жагынан... Ишкердин батпай турган жан дүйнөсүн бир нерсе тырмап жатат... Эмне болуп жатканын аныктап көрөлү. Биринчиден, заводдордун көптүгү. Ар бир жолу жаңы пункт үчүн өзүңүздүн фабрикаңызды түзүүгө жана кофекананы түзүүдө талап кылынган фабриканын конструкторго өткөрүлүп берorшине ынануу мүмкүнбү? Экинчиден, ал дагы эле жөнөкөй завод. Бир аз модернизацияланган. Бул жерде дагы эле жаңы үлгүнү изилдеп жатабыз. Үчүнчүдөн, муну башкача жасоо мүмкүн эмеспи? 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()Башкача айтканда, жаратуучу класстарды ишке ашыруунун алкагында, жаратуучу класстын өзгөчөлүктөрүнүн негизинде белгилүү бир продуктуну даярдоо чечими кабыл алынат.
Эми сиз фабрикалык ыкма үлгүсүн аныктоого даярсыз . Заводдук ыкма үлгүсү an objectти түзүү үчүн интерфейсти аныктайт, бирок субкласстарга түзүлө турган инстанциянын классын тандоого мүмкүндүк берет. Ошентип, Factory ыкмасы инстанциялоо операциясын субкласстарга өткөрүп берет. Жалпысынан алганда, аныктаманы эстеп калуу нерселердин кантип иштээрин түшүнүү сыяктуу маанилүү эмес.

Заводдук методдун структурасы

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

Үй тапшырма

Ошентип, бүгүн биз абдан көп иштерди жасадык жана фабрикалык ыкма дизайн үлгүсүн изилдеп чыктык. Сиз өткөн материалды консолидациялоого убакыт келди! Тапшырма 1. Дагы бир кофекана ачуунун үстүндө иштөө. Бул англис же испан стorнде жасалган болушу мүмкүн. Же ал тургай космостук кеменин стorнде. Кофенин жаркырап турушу үчүн тамак-аш боёкторун кошолу, жалпысынан кофе жөн гана мейкиндик болот! Тапшырма 2. Акыркы лекцияда сизде виртуалдык суши-бар же виртуалдык пиццерия түзүү милдети турган. Сиздин милдет бир орунда туруу эмес. Бүгүн сиз ийгorкке жетүү үчүн фабрикалык ыкманы кантип колдонууну үйрөндүңүз. Бул бorмден пайдаланып, өз бизнесиңизди кеңейтүүгө убакыт келди;)
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION