JavaRush /จาวาบล็อก /Random-TH /รูปแบบการออกแบบ: AbstractFactory

รูปแบบการออกแบบ: AbstractFactory

เผยแพร่ในกลุ่ม
สวัสดี! วันนี้เราจะมาศึกษารูปแบบการออกแบบและพูดคุยเกี่ยวกับโรงงานเชิงนามธรรม กัน ต่อ รูปแบบการออกแบบ: AbstractFactory - 1สิ่งที่เราจะทำในระหว่างการบรรยาย:
  • เรามาพูดคุยกันว่าโรงงานเชิงนามธรรมคืออะไร และรูปแบบนี้ช่วยแก้ปัญหาอะไร
  • เราจะสร้างกรอบการทำงานของแอปพลิเคชันข้ามแพลตฟอร์มสำหรับการสั่งกาแฟด้วยอินเทอร์เฟซผู้ใช้
  • เรามาศึกษาคำแนะนำในการใช้รูปแบบนี้ด้วยไดอะแกรมและโค้ด
  • โบนัสมีไข่อีสเตอร์ซ่อนอยู่ในการบรรยายซึ่งคุณจะได้เรียนรู้การกำหนดชื่อของระบบปฏิบัติการโดยใช้ Java และดำเนินการอย่างใดอย่างหนึ่งหรืออย่างอื่นขึ้นอยู่กับผลลัพธ์
เพื่อให้เข้าใจรูปแบบนี้อย่างถ่องแท้ คุณต้องมีความเข้าใจหัวข้อต่อไปนี้เป็นอย่างดี:
  • การสืบทอดใน Java;
  • คลาสนามธรรมและวิธีการใน Java

รูปแบบโรงงานเชิงนามธรรมแก้ปัญหาอะไรได้บ้าง

โรงงานเชิงนามธรรมก็เหมือนกับรูปแบบโรงงานอื่นๆ ที่ช่วยเราจัดระเบียบการสร้างวัตถุใหม่ๆ ได้อย่างถูกต้อง ด้วยความช่วยเหลือนี้ เราจึงจัดการ "การเผยแพร่" ของตระกูลต่างๆ ของอ็อบเจ็กต์ที่เชื่อมต่อถึงกัน ตระกูลต่างๆ ของวัตถุที่สัมพันธ์กัน...มันคืออะไร? ไม่ต้องกังวล: ในทางปฏิบัติทุกอย่างจะง่ายกว่าที่คิด เริ่มจากกลุ่มของวัตถุที่เกี่ยวข้องกันก่อน สมมติว่าคุณและฉันกำลังพัฒนากลยุทธ์และมีหน่วยรบหลายหน่วยอยู่ในนั้น:
  • ทหารราบ;
  • ทหารม้า;
  • นักธนู
หน่วยรบประเภทนี้เกี่ยวข้องกัน เนื่องจากทำหน้าที่ในกองทัพเดียวกัน เราสามารถพูดได้ว่าหมวดหมู่ที่ระบุไว้ข้างต้นเป็นตระกูลของวัตถุที่สัมพันธ์กัน ที่แยกออก แต่รูปแบบโรงงานเชิงนามธรรมถูกนำมาใช้เพื่อจัดระเบียบการสร้างวัตถุที่เชื่อมโยงถึงกันหลาย ตระกูล ไม่มีอะไรซับซ้อนที่นี่เช่นกัน เรามาต่อตัวอย่างด้วยกลยุทธ์กันดีกว่า พวกเขามักจะมีฝ่ายตรงข้ามที่แตกต่างกันหลายฝ่าย หน่วยรบของฝ่ายต่างๆ อาจมีลักษณะแตกต่างกันอย่างมาก ทหารราบ ทหารม้า และนักธนูของกองทัพโรมันไม่เหมือนกับทหารราบ ทหารม้า และนักธนูของพวกไวกิ้ง ภายในกรอบของกลยุทธ์ ทหารของกองทัพที่แตกต่างกันคือตระกูลที่แตกต่างกันของวัตถุที่เชื่อมโยงถึงกัน คงจะตลกดีถ้าเกิดความผิดพลาดของโปรแกรมเมอร์ ทหารในชุดฝรั่งเศสตั้งแต่สมัยนโปเลียนพร้อมปืนคาบศิลากำลังเดินไปรอบๆ ท่ามกลางทหารราบโรมัน เป็นการแก้ปัญหาที่จำเป็นต้องมีรูปแบบการออกแบบโรงงานเชิงนามธรรม ไม่ ไม่ใช่ปัญหาเรื่องความลำบากใจในการเดินทางข้ามเวลา แต่เป็นการสร้างกลุ่มวัตถุต่างๆ ที่เชื่อมโยงถึงกัน โรงงานนามธรรมจัดเตรียมอินเทอร์เฟซสำหรับการสร้างผลิตภัณฑ์ที่มีอยู่ทั้งหมด (วัตถุตระกูล) โดยทั่วไปโรงงานนามธรรมจะมีการใช้งานหลายอย่าง แต่ละคนมีหน้าที่รับผิดชอบในการสร้างผลิตภัณฑ์ในรูปแบบใดรูปแบบหนึ่ง ในฐานะที่เป็นส่วนหนึ่งของกลยุทธ์ เราจะมีโรงงานที่เป็นนามธรรมซึ่งสร้างทหารราบ นักธนู และทหารม้าที่เป็นนามธรรม รวมถึงการปรับใช้โรงงานแห่งนี้ โรงงานที่สร้างกองทหารโรมัน และตัวอย่าง โรงงานที่สร้างนักรบคาร์เธจ นามธรรมเป็นหลักการที่สำคัญที่สุดของรูปแบบนี้ ลูกค้าโรงงานทำงานร่วมกับมันและผลิตภัณฑ์ผ่านอินเทอร์เฟซแบบนามธรรมเท่านั้น ดังนั้นเราจึงไม่จำเป็นต้องคิดว่าเรากำลังสร้างนักรบประเภทใดอยู่ในขณะนี้ แต่โอนความรับผิดชอบนี้ไปสู่การใช้งานโรงงานเชิงนามธรรมโดยเฉพาะ

เรายังคงดำเนินการร้านกาแฟแบบอัตโนมัติต่อไป

ในการบรรยายครั้งล่าสุดเราได้ศึกษารูปแบบวิธีการของโรงงาน ซึ่งช่วยให้เราขยายธุรกิจกาแฟและเปิดจุดจำหน่ายกาแฟแห่งใหม่ได้หลายแห่ง วันนี้เราจะทำงานต่อไปเพื่อปรับปรุงธุรกิจของเราให้ทันสมัย เราจะวางรากฐานสำหรับแอปพลิเคชันเดสก์ท็อปใหม่สำหรับการสั่งกาแฟออนไลน์โดยใช้รูปแบบโรงงานแบบนามธรรม เมื่อเราเขียนแอปพลิเคชันสำหรับเดสก์ท็อป เราควรคิดถึงข้ามแพลตฟอร์มเสมอ แอปพลิเคชันของเราควรทำงานได้ทั้งบน macOS และ Windows (สปอยเลอร์: Linux จะถูกทิ้งไว้ให้คุณเป็นการบ้าน) ใบสมัครของเราจะเป็นอย่างไร? ค่อนข้างง่าย: นี่จะเป็นแบบฟอร์มที่ประกอบด้วยช่องข้อความ ช่องเลือก และปุ่ม หากคุณมีประสบการณ์ในการใช้ระบบปฏิบัติการที่แตกต่างกัน คุณจะสังเกตได้อย่างแน่นอนว่าบน Windows ปุ่มต่างๆ จะแสดงผลแตกต่างไปจากบน Mac เช่นเดียวกับทุกสิ่งทุกอย่าง... มาเริ่มกันเลย ในบทบาทของตระกูลผลิตภัณฑ์ ดังที่คุณคงเข้าใจแล้ว เราจะมีองค์ประกอบอินเทอร์เฟซแบบกราฟิก:
  • ปุ่ม;
  • ช่องข้อความ;
  • ช่องสำหรับการเลือก
ข้อสงวนสิทธิ์ ภายในแต่ละอินเทอร์เฟซเราสามารถกำหนดวิธีการเช่นonClickหรือ เหล่านั้น. วิธีการที่จะช่วยให้เราจัดการเหตุการณ์ต่างๆ ได้ (การคลิกปุ่ม การป้อนข้อความ การเลือกค่าในกล่องเลือก) ทั้งหมดนี้จงใจละเว้นเพื่อไม่ให้ตัวอย่างมากเกินไปและเพื่อให้มองเห็นได้ชัดเจนยิ่งขึ้นสำหรับการศึกษารูปแบบของโรงงาน มากำหนดอินเทอร์เฟซแบบนามธรรมสำหรับผลิตภัณฑ์ของเรา: onValueChangedonInputChanged
public interface Button {}
public interface Select {}
public interface TextField {}
สำหรับแต่ละระบบปฏิบัติการ เราต้องสร้างองค์ประกอบอินเทอร์เฟซตามสไตล์ของระบบปฏิบัติการนั้น เราเขียนสำหรับ Windows และ MacOS มาสร้างการใช้งานสำหรับ Windows กันเถอะ:
public class WindowsButton implements Button {
}

public class WindowsSelect implements Select {
}

public class WindowsTextField implements TextField {
}
ตอนนี้เหมือนกันสำหรับ MacOS:
public class MacButton implements Button {
}

public class MacSelect implements Select {
}

public class MacTextField implements TextField {
}
ยอดเยี่ยม. ตอนนี้เราสามารถเริ่มต้นโรงงานนามธรรมของเราได้ ซึ่งจะสร้างประเภทผลิตภัณฑ์นามธรรมที่มีอยู่ทั้งหมด:
public interface GUIFactory {

    Button createButton();
    TextField createTextField();
    Select createSelect();

}
สมบูรณ์แบบ. อย่างที่คุณเห็น ยังไม่มีอะไรซับซ้อนจนถึงตอนนี้ จากนั้นทุกอย่างก็เรียบง่ายเหมือนกัน โดยการเปรียบเทียบกับผลิตภัณฑ์ เราสร้างการใช้งานโรงงานของเราที่แตกต่างกันสำหรับแต่ละระบบปฏิบัติการ เริ่มต้นด้วย Windows:
public class WindowsGUIFactory implements GUIFactory {
    public WindowsGUIFactory() {
        System.out.println("Creating gui factory for Windows OS");
    }

    public Button createButton() {
        System.out.println("Creating Button for Windows OS");
        return new WindowsButton();
    }

    public TextField createTextField() {
        System.out.println("Creating TextField for Windows OS");
        return new WindowsTextField();
    }

    public Select createSelect() {
        System.out.println("Creating Select for Windows OS");
        return new WindowsSelect();
    }
}
มีการเพิ่มเอาต์พุตคอนโซลภายในวิธีการและตัวสร้างเพื่อสาธิตวิธีการทำงานเพิ่มเติม ตอนนี้สำหรับ macOS:
public class MacGUIFactory implements GUIFactory {
    public MacGUIFactory() {
        System.out.println("Creating gui factory for macOS");
    }

    @Override
    public Button createButton() {
        System.out.println("Creating Button for macOS");
        return new MacButton();
    }

    @Override
    public TextField createTextField() {
        System.out.println("Creating TextField for macOS");
        return new MacTextField();
    }

    @Override
    public Select createSelect() {
        System.out.println("Creating Select for macOS");
        return new MacSelect();
    }
}
หมายเหตุ: แต่ละวิธีจะส่งคืนประเภทนามธรรมตามลายเซ็น แต่ภายในวิธีการนั้น เราได้สร้างการนำผลิตภัณฑ์ไปใช้อย่างเป็นรูปธรรม นี่เป็นที่เดียวที่เราควบคุมการสร้างอินสแตนซ์เฉพาะ ตอนนี้ได้เวลาเขียนคลาสแบบฟอร์มแล้ว นี่คือคลาส Java ที่มีฟิลด์เป็นองค์ประกอบอินเตอร์เฟส:
public class OrderCoffeeForm {
    private final TextField customerNameTextField;
    private final Select coffeTypeSelect;
    private final Button orderButton;

    public OrderCoffeeForm(GUIFactory factory) {
        System.out.println("Creating order coffee form");
        customerNameTextField = factory.createTextField();
        coffeTypeSelect = factory.createSelect();
        orderButton = factory.createButton();
    }
}
โรงงานนามธรรมจะถูกส่งผ่านไปยังตัวสร้างแบบฟอร์ม ซึ่งสร้างองค์ประกอบอินเทอร์เฟซ เราจะส่งการใช้งานจากโรงงานที่จำเป็นไปยังตัวสร้าง เพื่อให้เราสามารถสร้างองค์ประกอบอินเทอร์เฟซสำหรับระบบปฏิบัติการเฉพาะได้
public class Application {
    private OrderCoffeeForm orderCoffeeForm;

    public void drawOrderCoffeeForm() {
        // Определим Name операционной системы, получив meaning системной проперти через System.getProperty
        String osName = System.getProperty("os.name").toLowerCase();
        GUIFactory guiFactory;

        if (osName.startsWith("win")) { // Для windows
            guiFactory = new WindowsGUIFactory();
        } else if (osName.startsWith("mac")) { // Для mac
            guiFactory = new MacGUIFactory();
        } else {
            System.out.println("Unknown OS, can't draw form :( ");
            return;
        }
        orderCoffeeForm = new OrderCoffeeForm(guiFactory);
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.drawOrderCoffeeForm();
    }
}
หากเรารันแอปพลิเคชันบน Windows เราจะได้ผลลัพธ์ดังต่อไปนี้:

Creating gui factory for Windows OS
Creating order coffee form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
บน Mac ผลลัพธ์จะเป็นดังนี้:

Creating gui factory for macOS
Creating order coffee form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
บนลินุกซ์:

Unknown OS, can't draw form :( 
คุณและฉันได้ข้อสรุปดังต่อไปนี้ เราเขียนเฟรมเวิร์กสำหรับแอปพลิเคชัน GUI ที่สร้างองค์ประกอบอินเทอร์เฟซที่เหมาะสมสำหรับระบบปฏิบัติการที่กำหนด ให้เราทำซ้ำสิ่งที่เราสร้างขึ้น:
  • ตระกูลผลิตภัณฑ์: ช่องป้อนข้อมูล ช่องเลือก และปุ่ม
  • การใช้งานต่างๆ ของผลิตภัณฑ์ตระกูลนี้ สำหรับ Windows และ macOS
  • โรงงานเชิงนามธรรม ซึ่งภายในเราได้กำหนดอินเทอร์เฟซสำหรับการสร้างผลิตภัณฑ์ของเรา
  • การใช้งานโรงงานของเราสองครั้ง โดยแต่ละขั้นตอนมีหน้าที่รับผิดชอบในการสร้างกลุ่มผลิตภัณฑ์ที่เฉพาะเจาะจง
  • แบบฟอร์มคลาส Java ซึ่งมีฟิลด์เป็นองค์ประกอบอินเทอร์เฟซแบบนามธรรมที่เริ่มต้นในตัวสร้างด้วยค่าที่ต้องการโดยใช้โรงงานแบบนามธรรม
  • คลาสแอปพลิเคชัน ภายในนั้น เราสร้างแบบฟอร์มที่เราส่งต่อการดำเนินการที่จำเป็นของโรงงานของเราไปยังผู้สร้าง
ทั้งหมด: เราได้นำรูปแบบโรงงานที่เป็นนามธรรมไปใช้

โรงงานบทคัดย่อ: คำแนะนำสำหรับการใช้งาน

Abstract Factory คือรูปแบบการออกแบบสำหรับจัดการการสร้างตระกูลผลิตภัณฑ์ที่แตกต่างกัน โดยไม่เชื่อมโยงกับประเภทผลิตภัณฑ์เฉพาะ เมื่อใช้เทมเพลตนี้ คุณต้อง:
  1. กำหนดกลุ่มผลิตภัณฑ์ด้วยตนเอง สมมติว่าเรามีสองอัน:
    • SpecificProductA1,SpecificProductB1
    • SpecificProductA2,SpecificProductB2
  2. สำหรับแต่ละผลิตภัณฑ์ภายในกลุ่ม ให้กำหนดคลาสนามธรรม (อินเทอร์เฟซ) ในกรณีของเราคือ:
    • ProductA
    • ProductB
  3. ภายในแต่ละตระกูลผลิตภัณฑ์ แต่ละผลิตภัณฑ์ต้องใช้อินเทอร์เฟซที่กำหนดไว้ในขั้นตอนที่ 2
  4. สร้างโรงงานเชิงนามธรรม ด้วยการสร้างวิธีการสำหรับแต่ละผลิตภัณฑ์ที่กำหนดไว้ในขั้นตอนที่ 2 ในกรณีของเรา วิธีการเหล่านี้จะเป็น:
    • ProductA createProductA();
    • ProductB createProductB();
  5. สร้างการใช้งานโรงงานนามธรรมเพื่อให้การใช้งานแต่ละครั้งควบคุมการสร้างผลิตภัณฑ์ในตระกูลเดียวกัน ในการทำเช่นนี้ ภายในการใช้งานโรงงานเชิงนามธรรมแต่ละครั้ง จำเป็นต้องใช้วิธีการสร้างทั้งหมด เพื่อให้มีการสร้างและส่งคืนการใช้งานที่เป็นรูปธรรมของผลิตภัณฑ์
ด้านล่างนี้เป็นแผนภาพ UML ที่แสดงคำแนะนำที่อธิบายไว้ข้างต้น รูปแบบการออกแบบ: AbstractFactory - 3ตอนนี้เรามาเขียนโค้ดสำหรับคำสั่งนี้กันดีกว่า:
// Определим общие интерфейсы продуктов
public interface ProductA {}
public interface ProductB {}

// Создадим различные реализации (семейства) наших продуктов
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}

public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}

// Создадим абстрактную фабрику
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory1 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB1();
    }
}

// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory2 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB2();
    }
}

การบ้าน

หากต้องการรวมเนื้อหา คุณสามารถทำได้ 2 สิ่ง:
  1. ปรับปรุงแอปพลิเคชั่นสั่งกาแฟให้ทำงานบน Linux
  2. สร้างโรงงานเชิงนามธรรมของคุณเองเพื่อผลิตหน่วยกลยุทธ์ต่างๆ นี่อาจเป็นกลยุทธ์ทางประวัติศาสตร์ที่มีกองทัพจริงหรือแฟนตาซีกับออร์ค คนแคระ และเอลฟ์ สิ่งสำคัญคือคุณพบว่ามันน่าสนใจ สร้างสรรค์ โพสต์หมุดบนคอนโซล และสนุกไปกับการเรียนรู้รูปแบบ!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION