JavaRush /Java блогы /Random-KK /Зауыттық әдіс және дерексіз зауыттық үлгілер

Зауыттық әдіс және дерексіз зауыттық үлгілер

Топта жарияланған
Кітапта «Алдымен бас. Дизайн үлгілері» бұл үлгілерді келесідей анықтайды: Зауыттық әдіс үлгісі нысанды жасауға арналған интерфейсті анықтайды, бірақ ішкі сыныптарға жасалатын дананың сыныбын таңдауға мүмкіндік береді. Осылайша, Factory әдісі даналық әрекетті ішкі сыныптарға береді. Abstract Factory үлгісі нақты сыныптарын көрсетпестен өзара байланысты немесе өзара тәуелді нысандардың отбасыларын құруға арналған интерфейсті қамтамасыз етеді. Мұны толығырақ түсінуге тырысайық. Сіз монах болуға шешім қабылдаған адамдар туралы ойын жазуды шештіңіз делік . Біз келесіден бастай аламыз. 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;
    }
}
сондықтан монахтардың жаңа түрлері енгізілген сайын жаңа класс жасап, барын өңдеуге тура келеді. Бұл жағдайда біздің монастырь сыныбын өзгерістерден «инкапсуляциялау» үшін не істеуге болады. Зауыттық әдіс үлгісін пайдаланып көруге болады. Бұл қалай көрінеді 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("Я англиканский монах");
    }
}
B) Монастырь класын келесідей өзгертейік (оны және оның әдісін абстрактілі етіп көрсетейік). Мұнда біз жай ғана Фабрика әдісін қолданамыз :
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();
    }
}
Я православный монах
Я католический монах
Я англиканский монах
Анау. біз қазір көріп отырғанымыздай, монахтардың жаңа түрлерін қосқанда, бұрыннан бар сыныптарды өзгертудің қажеті жоқ, бірақ қажет болған жағдайда жаңаларын (белгілі бір монастыр мен монах класы) қосыңыз. Мүмкін, біреу Монк класында басынан бері сипатталған әдістің де Фабрика екенін байқаған шығар :) Зауыттық әдістің анықтамасы біздің үлгі нысанды құру интерфейсін анықтайтынын айтты, бірақ біз оны жасамадық. интерфейстер, дегенмен біз Monastery класын интерфейс ретінде жасай аламыз және оны нақты іске асыруда жүзеге асыра аламыз. Бұл кеңірек мағынада «интерфейс» сөзін білдіреді. Анықтама сонымен қатар ішкі сыныптарға өздері жасайтын дананың класын таңдауға мүмкіндік беретінін айтты . Мұнда біз тек ішкі сыныптардың (бала сыныптар) бұл әдісті жүзеге асыратынын көреміз (яғни, монах an objectілерін жасау үшін бұл өкілеттіктер оларға берілген). Енді бағдарламамызды сәл кеңейтіп, бір немесе басқа конфессияда әртүрлі монахтардың болуы мүмкіндігін енгізейік. Мысалы, православиеде православие шіркеуінің монастырлар мен монастырлар туралы ұстанымына (Орыс православие шіркеуінің епископтар кеңесінде 2017 жылғы 29 қараша - 2 желтоқсанда қабылданған) негізделген монахтардың 2 түрі бар деп қорытынды жасауға болады. : - Кіші схема (мантия). - Схема (үлкен схема). Сондай-ақ «дайындық кезеңдері» бар, бірақ адамдар монахтар болып саналмайды (Трудник, Новичок және Рясофор немесе Монк), өйткені олар монастырлық ант бермейді. Сондықтан біз оларды есепке алмаймыз. Бұл жағдайда біз не аламыз: 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);
    }
}
B) Монах класын түзетейік:
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) Кодымызды тексерейік:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
Осылайша, Зауыттық әдіс үлгісін қолдану арқылы біз бұрын жазылған сыныптарды өзгертудің қажеті жоқ, сонымен қатар монахтардың кескіндерін (түрлерін) кеңейту кезінде 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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Киім тігетін фабрика жақсы жұмыс істей бастады. Енді сіз зауытқа сәтті дұға ету үшін монахтарға арналған жабдық өндірісін қосуға болады (тәспі моншақтар және т.б.). Бірақ сұрақ әлі де қалады: 2 үлгіні бірге қолдануға бола ма? Әрине, сіз жасай аласыз :) Жобамыздың соңғы нұсқасын жасап көрейік және индус монахын қосайық: 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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
Қорытындылай келе, Фабрика әдісі ішкі сыныптарда іске асырылған іске асырылмаған әдіспен абстрактілі классты пайдаланғанын, ал Abstract Factory интерфейсті пайдаланғанын атап өтуге болады, онда іске асыру (біздің жағдайда, монах құру) оны жүзеге асырған сыныптарда орын алды. интерфейс.
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION