JavaRush /Java блогу /Random-KY /Заводдук метод жана абстракттуу фабрикалык моделдер

Заводдук метод жана абстракттуу фабрикалык моделдер

Группада жарыяланган
Китепте «Биринчи баш. Дизайн үлгүлөрү” бул үлгүлөрдү төмөнкүчө аныктайт: Заводдук метод үлгүсү an objectти түзүү үчүн интерфейсти аныктайт, бирок субкласстарга түзүлө турган инстанциянын классын тандоого мүмкүндүк берет. Ошентип, Factory ыкмасы инстанциялоо операциясын субкласстарга өткөрүп берет. Абстракттуу фабрика үлгүсү өз ара байланышкан же өз ара көз каранды an objectтердин үй-бүлөлөрүн алардын конкреттүү класстарын көрсөтпөстөн түзүү үчүн интерфейсти камсыз кылат. Муну кененирээк түшүнүүгө аракет кылалы. Сиз... (бул жерде сизге оригиналдуу жана адаттан тыш нерсе керек) монах болууну чечкен адамдар жөнүндө оюн жазууну чечтиңиз дейли . Биз төмөнкүлөрдөн баштасак болот. 1) Монк классын жана балдар класстарын түзүңүз (биринчи түзөлү):
public abstract class Monk {

    public abstract void description();
}
public class OrthodoxMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я православный монах");
    }
}
2) Жана, албетте, монастырдык классты түзүңүз, анда сиз "монастырдык анттарды" ишке ашыра аласыз:
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;
    }
}
Келгиле, натыйжаны текшерип көрөлү:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new Monastery();
        monastery.createMonk("ORTODOX");
        monastery.getMonk().description();
    }
}
Я православный монах
Эми сиз католик монах түзүшүңүз керек болсо, анда сизге A) Католик монах үчүн жаңы класс түзүү керек:
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
B) Монастырдык класска өзгөртүүлөрдү киргизүү:
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;
    }
}
Ошентип, монахтардын жаңы түрлөрү киргизилген сайын, сиз жаңы класс түзүп, учурдагысын түзөтүшүңүз керек болот. Бул учурда биздин монастырдык классыбызды өзгөрүүлөрдөн кандайдыр бир жол менен "инкапсуляциялоо" үчүн эмне кылса болот. Сиз Factory Method үлгүсүн колдонуп көрүңүз. Бул кандай болот A) Келгиле, монахтар классын ошол бойдон калтыралы, балким англикандык монахты кошпойлу (католиктерде жана православдык христиандарда гана монастырдык эмес):
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("Я англиканский монах");
    }
}
Б) Монастырлык классты төмөнкүдөй өзгөртөлү (аны жана анын ыкмасын абстракттуу кылалы). Бул жерде биз жөн гана Factory ыкмасын колдонобуз :
public abstract class Monastery {
    protected abstract Monk createMonk();
}
жана методду ишке ашыруу менен балдар класстарын түзүү:
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) Кодду текшерип көрөлү
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();
    }
}
Я православный монах
Я католический монах
Я англиканский монах
Ошол. биз азыр көрүп тургандай, монахтардын жаңы түрлөрүн кошууда, учурдагы класстарды өзгөртүүнүн кереги жок болот, бирок зарыл болгондо гана жаңыларын (белгилүү бир монастырдын жана монахтын классы) кошуу керек. Мүмкүн, кимдир бирөө Монк классында башынан эле болгон сыпаттоо ыкмасы да Factory болгонун байкагандыр :) Заводдук методдун аныктамасы биздин үлгү an objectти түзүү үчүн интерфейсти аныктайт деп айткан, бирок биз эч нерсе жараткан жокпуз. интерфейстер, бирок биз Monastery классын интерфейс катары түзүп, аны конкреттүү ишке ашырууда ишке ашыра алабыз. Бул кененирээк мааниде "интерфейс" деген сөздү билдирет. Аныктама ошондой эле субкласстарга алар түзгөн инстанциянын классын тандоого мүмкүндүк берет деп айтылат . Бул жерде биз жөн гана субкласстар (балдар класстары) бул ыкманы ишке ашырып жатканын көрөбүз (башкача айтканда, монах an objectилерин түзүү үчүн бул ыйгарым укуктар аларга берилген). Эми программабызды бир аз кеңейтели, тигил же бул конфессияда ар кандай монахтар болушу мүмкүндүгүн киргизели. Мисалы, православиеде монастырлар жана монастырлар боюнча православ чиркөөсүнүн позициясына таянуу менен (2017-жылдын 29-ноябрынан 2-декабрында Орус Православ чиркөөсүнүн епископтор кеңешинде кабыл алынган) монахтардын 2 түрү бар деген тыянак чыгарууга болот. : - Кичинекей схема (мантия). - схема (улуу схема). Ошондой эле "даярдык этаптары" бар, бирок адамдар монахтар (Трудник, Новичок жана Рясофор же Монк) болуп саналbyte, анткени алар монастырдык ант беришпейт. Ошондуктан биз аларды эске албайбыз. Бул учурда биз эмнеге ээ болобуз: A) Монастырлык класс (жөнөкөйлөшүү үчүн, азыр православдык монастырга көңүл буралы) Фабрика ыкмасы менен :
public abstract class Monastery {
    protected abstract Monk createMonk(String type);
}
жана белгилүү бир монастырь
public class OrthodoxMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new OrthodoxMonk(type);
    }
}
Б) Кечил классты оңдойлу:
public abstract class Monk {
    String kind;

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

    public abstract void description();
}
жана бала классы:
public class OrthodoxMonk extends Monk {
    public OrthodoxMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я православный монах - " + kind);
    }
}
C) Биздин codeду текшерип көрөлү:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
Ошентип, Factory Method үлгүсүн колдонуу менен биз мурда жазылган класстарды өзгөртүүнүн кереги жок экендигине жетиштик, бирок монахтардын сүрөттөрүн (типтерин) кеңейтүүдө codeду минималдуу өзгөртүү талап кылынат. Келгиле, католик монахтарынын бардык буйруктарын жана жыйналыштарын текшерип, кошуп көрөлү :) Бирок эң атактуу 3кө токтолгон жакшы, анткени алардын саны 100дөн ашат: 1) Бенедиктин 2) Иезуит 3) Францискан Бул үчүн мурункудай эле ортодокс монах, биз католик монах белгилүү бир классты ишке ашыруу керек:
public class CatholicMonk extends Monk {
    public CatholicMonk(String kind) {
        super(kind);
    }

    @Override
    public void description() {
        System.out.println("Я католический монах - " + kind);
    }
}
жана монастырдык класс:
public class CatholicMonastery extends Monastery {

    @Override
    protected Monk createMonk(String type) {
        return new CatholicMonk(type);
    }
}
жана codeду текшерүү:
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();
    }
}
Я православный монах - Мантийный монах
Я православный монах - Великосхимник
Я католический монах - Бенедиктинец
Я католический монах - Иезуит
Я католический монах - Францисканец
Ушул үлгү менен бүтүрөлү. Бул монахтардын бардык түрлөрүн алдын ала E-num классына кошууга болот, бирок codeду жөнөкөйлөтүү үчүн биз ансыз жасайбыз. Абстракттуу фабрика үлгүсүнө убакыт келди. Бизде монахтар бар, эми аларга кийим, теспе ж.б. жасамакпыз. Кийимден баштайлы, башкача айтканда, башында өзүбүздүн аныктамабызга кайрылсак, кийим өз ара байланышкан же бири-бирине көз каранды an objectтердин үй-бүлөсүнө айланат . Маселеден баштайлы, монахтардын ар бир түрүнүн ар кандай кийимдери бар. Эгерде биз буддистти да кошсок, анда алар такыр башкача болот :) Бул үчүн биз фабриканын интерфейсин түзө алабыз, анын ишке ашырылышы керектүү кийимдерди түзө турган. Ошондуктан А) Кийим тигүү фабрикасын түзөбүз
public interface MonkFactory {
    Clothing createClothing();
}
жана аны ишке ашыруу
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();
    }
}
Келгиле, буддист монахтарды унутпайлы :)
public class BuddhistMonkFactory implements MonkFactory {

    @Override
    public Clothing createClothing() {
        return new BuddhistClothing();
    }
}
B) Кийимдердин классын түзүңүз (жөнөкөйлөшүү үчүн монахтардын кийиминин негизги элементин алалы, биз майда-чүйдөсүнө чейин айтпайбыз):
public abstract class Clothing {
    private String name;

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

    public String getName() {
        return name;
    }
}
жана балдар класстары
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) Андан кийин, биз монахтардын класстарын алардын кийимдери болушу үчүн алмаштырабыз:
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) Монастырдык класста биздин Фабрика методубуз бар
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);
}
биздин ишке ашыруу өзгөргөн жок
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) Жыйынтыгын текшерүү:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Кийим тигуучу фабрика жакшы иштей баштады. Эми сиз фабрикага монахтар үчүн ийгorктүү намаз окуу үчүн жабдууларды (теспе мончок, ж.б.) кошууга болот. Бирок суроо дагы эле бойдон калууда, 2 үлгүнү чогуу колдонуу мүмкүнбү? Албетте, сиз жасай аласыз :) Келгиле, долбоорубуздун акыркы versionсын жасап, индус монахын кошолу: A) Заводдор азыр монахтарды жаратууда "жылдыз фабрикасы" сыяктуу угулат :
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) Монастырдык класс + Монастырдык класстын конкреттүү ишке ашыруунун кереги жок, аларды завод ишке ашырат (тескерисинче, биз аларды таштап, заводдорду алып салышыбыз мүмкүн, бирок маңызы боюнча алар заводдордун ордуна жөн гана бул учурда монастырды абстракттуу класс эмес, интерфейс кылыш керек). Жана колдонмо классын кошуу:
public class Application {

    public Monk create(MonkFactory monkFactory, String type) {
        Monk monk = monkFactory.createMonk(type);
        monk.prepare(monkFactory);
        return monk;
    }
}
B) Монахтар азыр камтыйт
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);
}
Ишке ашырууда заводдук ыкманы камтыйт, ал фабрика аркылуу ишке ашырылат:
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) Жана текшерип көрөлү:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
Жыйынтыктап айтканда, Factory Method субкласстарда ишке ашырылган абстракттуу классты колдонгонун, ал эми абстракттуу фабрика интерфейсти колдонгонун белгилей аласыз, анда ишке ашыруу (биздин учурда, монах түзүү) муну ишке ашырган класстарда болгон. интерфейс.
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION