JavaRush /مدونة جافا /Random-AR /طريقة المصنع وأنماط المصنع المجردة

طريقة المصنع وأنماط المصنع المجردة

نشرت في المجموعة
في كتاب "الرأس أولاً". تحدد "أنماط التصميم" هذه الأنماط على النحو التالي: يحدد نمط أسلوب المصنع الواجهة لإنشاء كائن، ولكنه يسمح للفئات الفرعية باختيار فئة المثيل الذي سيتم إنشاؤه. وبالتالي، يقوم أسلوب المصنع بتفويض عملية إنشاء مثيل إلى فئات فرعية. يوفر نمط 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();
    }
}
Я православный монах
الآن إذا كنت بحاجة إلى إنشاء... راهب كاثوليكي، فستحتاج إلى أ) إنشاء فصل جديد للراهب الكاثوليكي:
public class CatholicMonk extends Monk {
    @Override
    public void description() {
        System.out.println("Я католический монах");
    }
}
ب) إجراء تغييرات على فئة الدير:
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;
    }
}
وهكذا في كل مرة يتم فيها تقديم أنواع جديدة من الرهبان، سيتعين عليك إنشاء فصل جديد وتعديل الفصل الحالي. ما الذي يمكن فعله في هذه الحالة من أجل "تغليف" طبقة الدير لدينا بطريقة أو بأخرى من التغييرات. يمكنك تجربة استخدام نمط طريقة المصنع. كيف سيبدو أ) دعونا نترك طبقة الراهب كما هي، باستثناء ربما إضافة راهب أنجليكاني (ليس فقط الكاثوليك والمسيحيون الأرثوذكس هم من يمارسون الرهبنة):
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("Я англиканский монах");
    }
}
ب) لنغير صنف الدير كما يلي (لنجعله وطريقته مجردة). هنا نستخدم طريقة المصنع فقط:
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();
    }
}
ب) دعونا نتحقق من الكود
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();
    }
}
Я православный монах
Я католический монах
Я англиканский монах
أولئك. كما نرى الآن، عند إضافة أنواع جديدة من الرهبان، لن تكون هناك حاجة لتغيير الطبقات الموجودة، ولكن فقط إذا لزم الأمر، إضافة فئات جديدة (طبقة دير وراهب معين). ربما لاحظ شخص ما بالفعل أن طريقة الوصف، التي كانت منذ البداية في فئة Monk، كانت أيضًا مصنعًا :) ذكر تعريف طريقة المصنع أن نمطنا يحدد الواجهة لإنشاء كائن، لكننا لم نقم بإنشاء أي شيء الواجهات، على الرغم من أنه يمكننا إنشاء فئة Monastery كواجهة وتنفيذها في تطبيقات محددة. يشير هذا إلى كلمة "واجهة" بالمعنى الأوسع. ذكر التعريف أيضًا أنه يسمح للفئات الفرعية باختيار فئة المثيل الذي يقومون بإنشائه . هنا نرى فقط أن الفئات الفرعية (الفئات الفرعية) تنفذ هذه الطريقة (أي أن هذه الصلاحيات لإنشاء كائنات الراهب يتم تفويضها إليها). الآن دعونا نوسع برنامجنا قليلاً، ونقدم إمكانية وجود رهبان مختلفين في طائفة أو أخرى. على سبيل المثال، في الأرثوذكسية، بناءً على موقف الكنيسة الأرثوذكسية من الأديرة والرهبان (الذي تم اعتماده في مجلس أساقفة الكنيسة الأرثوذكسية الروسية في 29 نوفمبر - 2 ديسمبر 2017)، يمكننا أن نستنتج أن هناك نوعين من الرهبان : - المخطط الأصغر (الوشاح). - المخطط (مخطط عظيم). هناك أيضًا "مراحل تحضيرية"، لكن لا يعتبر الناس رهبانًا (ترودنيك، مبتدئ، رياسوفور أو راهب)، لأنهم لا يأخذون النذور الرهبانية. ولذلك لا نأخذها بعين الاعتبار. ماذا نحصل في هذه الحالة: أ) صف الدير (للتبسيط، دعونا نركز على الرهبنة الأرثوذكسية في الوقت الحالي) باستخدام طريقة المصنع :
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);
    }
}
ج) دعونا نتحقق من الكود الخاص بنا:
public class Main {
    public static void main(String[] args) {
        Monastery monastery = new OrthodoxMonastery();
        monastery.createMonk("Мантийный монах").description();
        monastery.createMonk("Великосхимник").description();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
وبالتالي، باستخدام نمط طريقة المصنع، حققنا أنه ليس من الضروري تغيير الفئات المكتوبة مسبقًا، ولكن عند توسيع صور (أنواع) الرهبان، يلزم الحد الأدنى من التغييرات في الكود. دعونا نتحقق ونضيف جميع رهبنات وتجمعات الرهبان الكاثوليك :) ولكن من الأفضل التركيز على الثلاثة الأكثر شهرة، لأن هناك أكثر من 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);
    }
}
وتحقق من الكود:
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 مسبقًا، ولكن لتبسيط الكود سنستغني عن ذلك. حان الوقت لنمط المصنع الملخص. لدينا رهبان، والآن يمكننا أن نصنع لهم الملابس والمسابح وما إلى ذلك. لنبدأ بالملابس، أي أننا إذا رجعنا إلى تعريفنا في البداية، فإن الملابس ستصبح عائلة من الأشياء المترابطة أو المترابطة . لنبدأ بمشكلة أن كل نوع من الرهبان له ثياب مختلفة. إذا أضفنا البوذية أيضًا، فسيكونون مختلفين تمامًا :) للقيام بذلك، يمكننا إنشاء واجهة مصنع، والتي من شأن تطبيقاتها إنشاء الملابس اللازمة. لذلك أ) نقوم بإنشاء مصنع لصنع الملابس
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();
    }
}
ب) أنشئ فئة ملابس (للتبسيط، لنأخذ العنصر الأساسي لملابس الرهبان، ولن نخوض في التفاصيل):
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("Кашая");
    }
}
ج) بعد ذلك نغير طبقات الرهبان بحيث يكون لهم ملابس:
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());
    }
}
د) يحتوي فصل الدير على طريقة المصنع الخاصة بنا
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);
    }
}
د) التحقق من النتيجة:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
بدأ المصنع الذي يصنع الملابس في العمل بشكل جيد. يمكنك الآن أن تضيف إلى المصنع إنتاج معدات للرهبان من أجل صلاة ناجحة (خرز المسبحة، وما إلى ذلك). ولكن يبقى السؤال: هل من الممكن استخدام نمطين معًا؟ بالطبع يمكنك ذلك :) دعنا نحاول إنشاء النسخة النهائية من مشروعنا وإضافة راهب هندوسي: أ) المصانع التي تُنشئ الرهبان الآن تبدو وكأنها "مصنع النجوم" :
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();
    }
}
ب) ليست هناك حاجة لطبقة الدير + تطبيقات ملموسة لطبقة الدير، يتم تنفيذها من قبل المصنع (على العكس من ذلك، يمكننا تركها وإزالة المصانع، ولكن في جوهرها ستكون ببساطة بدلاً من المصانع، فقط في في هذه الحالة يجب أن يكون الدير واجهة، وليس فئة مجردة). وأضف فئة التطبيق:
public class Application {

    public Monk create(MonkFactory monkFactory, String type) {
        Monk monk = monkFactory.createMonk(type);
        monk.prepare(monkFactory);
        return monk;
    }
}
ب) تحتوي الآن على الرهبان
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());
    }
}
د) ودعونا نتحقق:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
في الختام، يمكنك ملاحظة أن طريقة المصنع استخدمت فئة مجردة مع طريقة غير منفذة تم تنفيذها في فئات فرعية، واستخدمت طريقة المصنع واجهة، حيث حدث التنفيذ (في حالتنا، إنشاء راهب) في الفئات التي نفذت هذا واجهه المستخدم.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION