JavaRush /จาวาบล็อก /Random-TH /วิธีการจากโรงงานและรูปแบบโรงงานเชิงนามธรรม

วิธีการจากโรงงานและรูปแบบโรงงานเชิงนามธรรม

เผยแพร่ในกลุ่ม
ในหนังสือ “มุ่งหน้าก่อน. รูปแบบการออกแบบ” กำหนดรูปแบบเหล่านี้ดังต่อไปนี้: รูปแบบวิธีการจากโรงงานกำหนดอินเทอร์เฟซสำหรับการสร้างออบเจ็กต์ แต่อนุญาตให้คลาสย่อยเลือกคลาสของอินสแตนซ์ที่จะสร้าง ดังนั้นเมธอด Factory จะมอบหมายการดำเนินการสร้างอินสแตนซ์ให้กับคลาสย่อย รูปแบบ Abstract Factory จัดเตรียมอินเทอร์เฟซสำหรับการสร้างกลุ่มของวัตถุที่สัมพันธ์กันหรือพึ่งพาซึ่งกันและกัน โดยไม่ต้องระบุคลาสที่เป็นรูปธรรม ลองทำความเข้าใจเรื่องนี้โดยละเอียดยิ่งขึ้น สมมติว่าคุณตัดสินใจเขียนเกมเกี่ยวกับคนที่ตัดสินใจที่จะเป็น... (คุณต้องการสิ่งที่แปลกใหม่และไม่เหมือนใครที่นี่)พระภิกษุ เราสามารถเริ่มต้นด้วยสิ่งต่อไปนี้ 1) สร้างคลาส Monk และคลาสย่อย (มาสร้างคลาสกันก่อน):
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("Я англиканский монах");
    }
}
B) มาเปลี่ยนคลาสของอารามดังต่อไปนี้ (มาสร้างมันและวิธีการของมันให้เป็นนามธรรมกัน) ที่นี่เราใช้วิธี 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();
    }
}
Я православный монах
Я католический монах
Я англиканский монах
เหล่านั้น. ดังที่เราเห็นตอนนี้เมื่อเพิ่มพระประเภทใหม่ไม่จำเป็นต้องเปลี่ยนประเภทที่มีอยู่ แต่หากจำเป็นให้เพิ่มประเภทใหม่ (ประเภทของอารามและพระภิกษุเฉพาะ) บางทีอาจมีคนสังเกตเห็นแล้วว่าวิธีการอธิบายซึ่งมาจากจุดเริ่มต้นในคลาส Monk ก็เป็นFactory เช่นกัน :) คำจำกัดความของวิธี Factory บอกว่ารูปแบบของเรากำหนดอินเทอร์เฟซสำหรับการสร้างวัตถุแต่เราไม่ได้สร้างใด ๆ แม้ว่าเราจะสามารถสร้างคลาส Monastery เป็นอินเทอร์เฟซและนำไปใช้ในการใช้งานเฉพาะได้ นี่หมายถึงคำว่า "อินเทอร์เฟซ" ในความหมายที่กว้างกว่า คำจำกัดความยังระบุด้วยว่า อนุญาตให้คลาสย่อยเลือกคลาสของอินสแตนซ์ที่พวกเขาสร้างขึ้น ที่นี่เราเพิ่งเห็นว่าคลาสย่อย (คลาสย่อย) ใช้วิธีนี้ (นั่นคือ พลังเหล่านี้ในการสร้างวัตถุพระถูกมอบหมายให้กับคลาสเหล่านั้น) ทีนี้เรามาขยายโปรแกรมของเรากันสักหน่อย แนะนำความเป็นไปได้ที่จะมีพระภิกษุต่างกันนิกายเดียวหรือนิกายอื่น ตัวอย่างเช่นในออร์โธดอกซ์ตามตำแหน่งของคริสตจักรออร์โธดอกซ์ในเรื่องอารามและอาราม(รับเลี้ยงในสภาสังฆราชแห่งคริสตจักรออร์โธดอกซ์รัสเซียเมื่อวันที่ 29 พฤศจิกายน - 2 ธันวาคม 2560)เราสามารถสรุปได้ว่าพระภิกษุมี 2 ประเภท : - สคีมาน้อย (แมนเทิล) - สคีมา (สคีมาที่ดี) นอกจากนี้ยังมี "ขั้นตอนการเตรียมการ" แต่ผู้คนไม่ถือว่าเป็นพระภิกษุ (ตรุดนิก สามเณร และริโสฟอร์ หรือพระภิกษุ) เนื่องจากพวกเขาไม่รับคำสาบานของสงฆ์ ดังนั้นเราจึงไม่คำนึงถึงสิ่งเหล่านี้ เราได้อะไรในกรณีนี้: A) Monastery Class (เพื่อให้ง่ายขึ้น เรามาเน้นที่การบวชแบบออร์โธดอกซ์ในตอนนี้) ด้วยวิธี Factory :
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();
    }
}
Я православный монах - Мантийный монах
Я православный монах — Великосхимник
ดังนั้น ด้วยการใช้รูปแบบ Factory Method เราจึงพบว่าเราไม่จำเป็นต้องเปลี่ยนคลาสที่เขียนไว้ก่อนหน้านี้ แต่เมื่อขยายรูปภาพ (ประเภท) ของพระ ก็จำเป็นต้องเปลี่ยนแปลงโค้ดขั้นต่ำด้วย เรามาตรวจสอบและเพิ่มคำสั่งและคณะสงฆ์คาทอลิกทั้งหมดกันดีกว่า :) แต่เน้นไปที่ 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);
    }
}
และตรวจสอบรหัส:
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 ล่วงหน้าได้ แต่เพื่อให้โค้ดง่ายขึ้น เราจะดำเนินการโดยไม่มีมัน ถึงเวลาสำหรับรูปแบบ Abstract Factory เรามีพระภิกษุ เดี๋ยวนี้ทำผ้า ประคำ ฯลฯ ได้ เริ่มต้นด้วยเสื้อผ้านั่นคือถ้าเรากลับไปสู่คำจำกัดความของเราตั้งแต่ต้น เสื้อผ้าจะกลายเป็นครอบครัวของวัตถุที่เชื่อมโยงถึงกันหรือพึ่งพาอาศัยกัน เรามาเริ่มกันที่ปัญหาที่พระแต่ละประเภทมีจีวรที่แตกต่างกัน หากเราเพิ่มพุทธเข้าไปด้วยก็จะแตกต่างไปจากเดิมอย่างสิ้นเชิง :) ในการทำเช่นนี้เราสามารถสร้างอินเทอร์เฟซของโรงงานซึ่งการดำเนินการดังกล่าวจะสร้างเสื้อผ้าที่จำเป็น ดังนั้น ก) เราจึงสร้างโรงงานผลิตเสื้อผ้าขึ้นมา
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("Кашая");
    }
}
ค) ต่อไปเราเปลี่ยนลำดับชั้นของพระภิกษุให้มีเครื่องนุ่งห่ม:
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();
    }
}
Я православный монах - Мантийный монах
Моя одежда - Мантия
Я католический монах - Иезуит
Моя одежда - Ряса с капюшоном
Я англиканский монах - Бенедиктинец
Моя одежда - Ряса
Я буддийский монах - Монах
Моя одежда - Кашая
Я индуистский монах - Саньяси
Моя одежда - Почти ничего, тепло же :)
โดยสรุป คุณสามารถสังเกตได้ว่าเมธอด Factory ใช้คลาสนามธรรมกับเมธอดที่ไม่ได้นำไปใช้ ซึ่งถูกนำไปใช้ในคลาสย่อย และ Abstract Factory ใช้อินเทอร์เฟซ โดยที่การใช้งาน (ในกรณีของเราคือการสร้างพระ) เกิดขึ้นในคลาสที่นำไปใช้ อินเทอร์เฟซนี้
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION