รูปแบบการออกแบบนามธรรมจากโรงงานและโรงงานแตกต่างกันอย่างไร


456

ฉันรู้ว่ามีโพสต์มากมายเกี่ยวกับความแตกต่างระหว่างสองรูปแบบ แต่มีบางสิ่งที่ฉันไม่สามารถหาได้

จากสิ่งที่ฉันได้อ่านฉันเห็นว่ารูปแบบวิธีการจากโรงงานอนุญาตให้คุณกำหนดวิธีการสร้างผลิตภัณฑ์คอนกรีตเพียงอย่างเดียว แต่ซ่อนการใช้งานจากลูกค้าเนื่องจากพวกเขาจะเห็นผลิตภัณฑ์ทั่วไป คำถามแรกของฉันเกี่ยวกับโรงงานที่เป็นนามธรรม บทบาทของมันคือการอนุญาตให้คุณสร้างตระกูลของวัตถุที่เป็นรูปธรรมใน (ซึ่งสามารถขึ้นอยู่กับโรงงานที่คุณใช้เฉพาะ) แทนที่จะเป็นวัตถุรูปธรรมเดียวหรือไม่ โรงงานนามธรรมส่งคืนวัตถุที่มีขนาดใหญ่มากหรือวัตถุจำนวนมากขึ้นอยู่กับวิธีการที่คุณเรียกใช้หรือไม่

คำถามสองข้อสุดท้ายของฉันเกี่ยวกับคำพูดเดียวที่ฉันไม่สามารถเข้าใจได้อย่างเต็มที่ว่าฉันเคยเห็นในหลายแห่ง:

ความแตกต่างอย่างหนึ่งระหว่างทั้งสองคือด้วยรูปแบบนามธรรมจากโรงงานชั้นเรียนได้มอบหมายความรับผิดชอบของการสร้างอินสแตนซ์ของวัตถุให้กับวัตถุอื่นผ่านการจัดองค์ประกอบในขณะที่รูปแบบวิธีการของโรงงานใช้การสืบทอดและอาศัยคลาสย่อยเพื่อจัดการ

ความเข้าใจของฉันคือรูปแบบวิธีการของโรงงานมีส่วนต่อประสานผู้สร้างที่จะทำให้ ConcreteCreator รับผิดชอบในการทราบว่า ConcreteProduct ใดที่จะยกตัวอย่าง นี่คือความหมายของการใช้การสืบทอดเพื่อจัดการการสร้างอินสแตนซ์ของวัตถุหรือไม่

ตอนนี้เกี่ยวกับคำพูดนั้นรูปแบบนามธรรมจากโรงงานจะมอบหมายความรับผิดชอบในการทำให้เป็นอินสแตนซ์ของวัตถุไปยังวัตถุอื่นผ่านองค์ประกอบได้อย่างไร สิ่งนี้หมายความว่า? ดูเหมือนว่ารูปแบบนามธรรมจากโรงงานยังใช้การสืบทอดเพื่อทำกระบวนการก่อสร้างเช่นกันในสายตาของฉัน แต่แล้วฉันก็ยังเรียนรู้เกี่ยวกับรูปแบบเหล่านี้อีกครั้ง

ความช่วยเหลือใด ๆ โดยเฉพาะอย่างยิ่งกับคำถามสุดท้ายจะได้รับการชื่นชมอย่างมาก



การดู "วิธีสร้างอินสแตนซ์" จากมุมมองของไคลเอ็นต์จะช่วยให้คุณเข้าใจคำพูด
Karthik Bose

@nawfal คำตอบในกระทู้นั้นแย่มาก
jaco0646

คำตอบ:


494

ความแตกต่างระหว่างคนทั้งสอง

ความแตกต่างที่สำคัญระหว่าง "วิธีการโรงงาน" และ "โรงงานนามธรรม" คือวิธีโรงงานเป็นวิธีการเดียวและโรงงานนามธรรมเป็นวัตถุ ฉันคิดว่าผู้คนจำนวนมากสับสนทั้งสองคำและเริ่มใช้พวกเขาสลับกันได้ ฉันจำได้ว่าฉันมีเวลายากที่จะหาสิ่งที่แตกต่างคือเมื่อฉันเรียนรู้พวกเขา

เนื่องจากวิธีการจากโรงงานเป็นเพียงวิธีการหนึ่งเท่านั้นจึงสามารถแทนที่ในคลาสย่อยดังนั้นในช่วงครึ่งหลังของการเสนอราคาของคุณ:

... รูปแบบวิธีการจากโรงงานใช้การสืบทอดและอาศัยคลาสย่อยเพื่อจัดการกับอินสแตนซ์ของวัตถุที่ต้องการ

อ้างว่าวัตถุเรียกวิธีโรงงานของตัวเองที่นี่ ดังนั้นสิ่งเดียวที่สามารถเปลี่ยนค่าส่งคืนจะเป็นคลาสย่อย

โรงงานนามธรรมเป็นวัตถุที่มีหลายวิธีในโรงงาน ดูครึ่งแรกของใบเสนอราคาของคุณ:

... ด้วยรูปแบบบทคัดย่อจากโรงงานชั้นเรียนจะมอบหมายความรับผิดชอบในการสร้างอินสแตนซ์ของวัตถุไปยังวัตถุอื่นผ่านการจัดองค์ประกอบ ...

สิ่งที่พวกเขาพูดคือมีวัตถุ A ที่ต้องการสร้างวัตถุ Foo แทนที่จะทำให้วัตถุ Foo ตัวเอง (เช่นด้วยวิธีโรงงาน) ก็จะได้รับที่แตกต่างกันของวัตถุ (โรงงานนามธรรม) เพื่อสร้างวัตถุ Foo

ตัวอย่างรหัส

เพื่อแสดงให้เห็นถึงความแตกต่างนี่คือวิธีการใช้งานจากโรงงาน:

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method 
        //to return something different
        return new SpecialFoo();
    }
}

และนี่คือโรงงานนามธรรมที่ใช้งานอยู่:

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here

15
นี่เป็นคำอธิบายที่ดีมาก แต่อะไรคือส่วนที่สำคัญที่สุดที่ยังไม่มีคำตอบและนั่นคือ: เมื่อใดควรใช้ส่วนใดส่วนหนึ่งและรูปแบบอื่นเมื่อใด
croraf

11
ไม่แน่ใจว่าถูกต้อง ค่อนข้างมั่นใจว่า Factory Method เป็นรูปแบบการออกแบบที่ตั้งชื่อตามวิธีการของโรงงาน แต่เกี่ยวข้องกับโครงสร้างคลาสและการสืบทอด มันไม่ใช่วิธีการเดียว
Aviv Cohn

2
ดังนั้นถูกต้องหรือไม่ที่จะพูดว่า: วิธีการจากโรงงานสามารถเป็นวิธีการในชั้นเรียนปกติทั้งหมดที่มีวัตถุประสงค์ที่แตกต่างกัน แต่ Abstract Factory เป็นคลาส / วัตถุที่ลูกค้าใช้และรับผิดชอบเฉพาะในการสร้างผลิตภัณฑ์บางอย่างในครอบครัวหรือไม่?
Hieu Nguyen

การที่คุณใช้คำว่า "Super" ใน "SuperFoo" นั้นหมายถึงกรณีพิเศษของ Foo หรือไม่หรือว่ามันหมายถึง super class? อย่างที่ฉันคิดว่ามันต้องเป็นคลาสย่อย
dahui

@dahui ใช่มันเป็นคลาสย่อย ฉันเปลี่ยนSpecialFooให้ชัดเจนยิ่งขึ้น
Tom Dalling

125

โรงงานนามธรรมสร้างคลาสฐานด้วยวิธีนามธรรมที่กำหนดวิธีการสำหรับวัตถุที่ควรสร้าง แต่ละคลาสของโรงงานซึ่งได้รับมาจากคลาสพื้นฐานสามารถสร้างการใช้งานของแต่ละประเภทของวัตถุ

ป้อนคำอธิบายรูปภาพที่นี่

วิธีการจากโรงงานเป็นเพียงวิธีง่าย ๆ ที่ใช้ในการสร้างวัตถุในชั้นเรียน มันมักจะถูกเพิ่มในรากรวม ( Orderชั้นมีวิธีการที่เรียกว่าCreateOrderLine)

ป้อนคำอธิบายรูปภาพที่นี่

โรงงานบทคัดย่อ

ในตัวอย่างด้านล่างเราออกแบบอินเทอร์เฟซเพื่อให้เราสามารถแยกการสร้างคิวจากระบบการส่งข้อความและสามารถสร้างการใช้งานสำหรับระบบคิวที่แตกต่างกันโดยไม่ต้องเปลี่ยนฐานรหัส

interface IMessageQueueFactory
{
  IMessageQueue CreateOutboundQueue(string name);
  IMessageQueue CreateReplyQueue(string name);
}

public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new AzureMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new AzureResponseMessageQueue(/*....*/);
      }

}

public class MsmqFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new MsmqMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new MsmqResponseMessageQueue(/*....*/);
      }
}

วิธีการโรงงาน

ปัญหาในเซิร์ฟเวอร์ HTTP คือเราต้องการคำตอบทุกคำขอเสมอ

public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

หากไม่มีวิธีการใช้งานจากโรงงานผู้ใช้เซิร์ฟเวอร์ HTTP (เช่นโปรแกรมเมอร์) จะถูกบังคับให้ใช้งานคลาสเฉพาะซึ่งเอาชนะวัตถุประสงค์ของIHttpRequestอินเทอร์เฟซ

ดังนั้นเราจึงแนะนำวิธีการของโรงงานเพื่อให้การสร้างคลาสการตอบสนองนั้นถูกตัดออกไป

สรุป

ความแตกต่างคือวัตถุประสงค์ที่ตั้งใจไว้ของคลาสที่มีวิธีการจากโรงงานไม่ได้สร้างวัตถุในขณะที่โรงงานนามธรรมควรใช้เพื่อสร้างวัตถุเท่านั้น

ควรใช้ความระมัดระวังเมื่อใช้วิธีการจากโรงงานเนื่องจากมันง่ายต่อการทำลาย LSP ( หลักการทดแทน Liskov ) เมื่อสร้างวัตถุ


3
ทำไมเราต้องการผลิตภัณฑ์คอนกรีต
แอนดรู S

60
เพราะไม่มีใครอยากลงทุนในความคิด
jgauffin

4
Abstract Factory ควรสร้างมากกว่าButton()เพื่อสร้าง "ตระกูลผลิตภัณฑ์ที่เกี่ยวข้อง" ยกตัวอย่างเช่นการบัญญัติ GoF ตัวอย่างเช่นสร้างและScrollBar() Window()ข้อได้เปรียบคือ Abstract Factory สามารถบังคับใช้ชุดรูปแบบทั่วไปในผลิตภัณฑ์ที่หลากหลาย
jaco0646

Jaco ถูกต้อง พิจารณาว่าแผนภาพ UML ทั้งสองนั้นเหมือนกัน (นอกเหนือจาก Abstract Factory UML ผิด) ในทั้งสองกรณีลูกค้ากำลังเรียกใช้วิธีการจากโรงงานเพื่อสร้างผลิตภัณฑ์เดียว
cobby

1
@AndrewS: เพื่อตอบคำถามของคุณ หากเราไม่จำเป็นต้องมีผลิตภัณฑ์คอนกรีต (คลาส) ที่แตกต่างกันสำหรับสิ่งที่เป็นนามธรรม (อินเทอร์เฟซ) เราอาจต้องใช้รูปแบบตัวสร้างแทนและไม่ใช่รูปแบบจากโรงงาน (ดีกว่าไม่สาย;))
jgauffin

95

ความแตกต่างระหว่าง AbstractFactory และรูปแบบการออกแบบโรงงานมีดังนี้:

  • วิธีการของโรงงานใช้เพื่อสร้างผลิตภัณฑ์เดียวเท่านั้น แต่Abstract Factoryเป็นเรื่องเกี่ยวกับการสร้างตระกูลของผลิตภัณฑ์ที่เกี่ยวข้องหรือผลิตภัณฑ์ที่เกี่ยวข้อง
  • รูปแบบวิธีการโรงงานเปิดเผยวิธีการให้กับลูกค้าสำหรับการสร้างวัตถุในกรณีของโรงงานบทคัดย่อพวกเขาเปิดเผยครอบครัวของวัตถุที่เกี่ยวข้องซึ่งอาจประกอบด้วยวิธีการโรงงานเหล่านี้
  • รูปแบบวิธีการของโรงงานซ่อนการก่อสร้างวัตถุชิ้นเดียวในขณะที่บทคัดย่อโรงงานซ่อนการก่อสร้างกลุ่มของวัตถุที่เกี่ยวข้อง บทคัดย่อโรงงานมักจะดำเนินการโดยใช้ (ชุด) วิธีการโรงงาน
  • บทคัดย่อรูปแบบโรงงานใช้องค์ประกอบเพื่อมอบหมายความรับผิดชอบในการสร้างวัตถุให้กับคลาสอื่นในขณะที่รูปแบบการออกแบบของวิธีใช้จากโรงงานใช้การสืบทอดและอาศัยคลาสที่ได้รับหรือคลาสย่อยเพื่อสร้างวัตถุ
  • แนวคิดเบื้องหลังรูปแบบวิธีการของโรงงานคืออนุญาตให้กรณีที่ไคลเอนต์ไม่ทราบว่าจะต้องสร้างคลาสที่เป็นรูปธรรมในเวลาทำงานเพียงแค่ต้องการรับคลาสที่จะทำงานในขณะที่ รูปแบบนามธรรมของโรงงานคือ ใช้ประโยชน์ได้ดีที่สุดเมื่อระบบของคุณต้องสร้างผลิตภัณฑ์หลายตระกูลหรือคุณต้องการจัดหาไลบรารีผลิตภัณฑ์โดยไม่ต้องเปิดเผยรายละเอียดการติดตั้ง!

รูปแบบวิธีการใช้จากโรงงาน: วิธีการโรงงาน UML

บทคัดย่อการใช้รูปแบบโรงงาน:

บทคัดย่อโรงงาน UML


13
อืมไม่แน่ใจเกี่ยวกับตัวอย่างจาก Abstract Factory ฉันคิดว่าโรงงานรูปทรงและโรงงานสีควรใช้วิธีการเดียวกัน แต่ถ้าฉันพูดถูกแล้วตัวอย่างก็ไม่มีเหตุผล
Joaquin Iurchuk

4
สัญลักษณ์แสดงหัวข้อถูกต้อง; อย่างไรก็ตามไดอะแกรมทั้งสองนั้นผิดทั้งหมดและทำให้เข้าใจผิดมาก ดูแผนภาพด้านล่างจาก @Trying สำหรับแบบจำลอง Abstract Factory ที่ถูกต้อง
jaco0646

1
ฉันต้องยอมรับ 2 ไดอะแกรมที่ทำให้เข้าใจผิดมาก ฉันเห็นพวกเขาในเว็บไซต์ tutorialspoint และบอกตามตรงฉันไม่เห็นด้วย 100% คำอธิบายนั้นดูดีมาก
SoftwareDeveloper

นี่เป็นสิ่งที่ทำให้เข้าใจผิดมาก
diyoda_

เกิน 50 ขึ้นไปและไดอะแกรมนั้นผิดมาก หลักฐานที่คุณไม่สามารถเชื่อถือได้คำตอบรูปแบบการออกแบบจำนวนมากในดังนั้น
Fuhrmanator

28

ความแตกต่างที่สำคัญระหว่างโรงงานบทคัดย่อและโรงงานวิธีคือการที่โรงงานบทคัดย่อดำเนินการโดยองค์ประกอบ ; แต่วิธีที่โรงงานจะดำเนินการโดยการรับมรดก

ใช่คุณอ่านถูกต้องแล้ว: ความแตกต่างที่สำคัญระหว่างสองรูปแบบนี้คือองค์ประกอบเก่ากับการถกเถียงกันเรื่องมรดก

แผนภาพ UML สามารถพบได้ในหนังสือ (GoF) ฉันต้องการให้ตัวอย่างโค้ดเนื่องจากฉันคิดว่าการรวมตัวอย่างจากคำตอบสองอันดับแรกในชุดข้อความนี้จะให้การสาธิตที่ดีกว่าคำตอบเดียว นอกจากนี้ฉันได้ใช้คำศัพท์จากหนังสือในชั้นเรียนและชื่อวิธีการ

โรงงานบทคัดย่อ

  1. จุดที่สำคัญที่สุดที่จะเข้าใจที่นี่คือโรงงานนามธรรมถูกฉีดเข้าไปในลูกค้า นี่คือเหตุผลที่เราพูดว่า Abstract Factory ถูกนำไปใช้โดย Composition บ่อยครั้งที่เฟรมเวิร์กการฉีดพึ่งพาจะทำหน้าที่นั้น แต่ไม่จำเป็นต้องมีเฟรมเวิร์กสำหรับ DI
  2. จุดวิกฤติที่สองคือโรงงานคอนกรีตที่นี่ไม่ใช่การใช้วิธีการของโรงงาน! โค้ดตัวอย่างสำหรับวิธีการจากโรงงานแสดงอยู่ด้านล่าง
  3. และสุดท้ายจุดที่สามที่ควรทราบคือความสัมพันธ์ระหว่างผลิตภัณฑ์: ในกรณีนี้คิวขาออกและตอบกลับ โรงงานคอนกรีตแห่งหนึ่งผลิตคิว Azure อีกแห่งหนึ่ง MSMQ GoF อ้างถึงความสัมพันธ์ผลิตภัณฑ์นี้ในฐานะ "ตระกูล" และเป็นสิ่งสำคัญที่ต้องระวังว่าตระกูลในกรณีนี้ไม่ได้หมายถึงลำดับชั้นของคลาส
public class Client {
    private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }

    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }

    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }
}

public interface AbstractFactory_MessageQueue {
    OutboundQueue createProductA();
    ReplyQueue createProductB();
}

public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new AzureMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }
}

public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new MsmqMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }
}

วิธีการโรงงาน

  1. จุดที่สำคัญที่สุดที่จะเข้าใจที่นี่ก็ConcreteCreator คือลูกค้า ในคำอื่น ๆ ลูกค้าเป็น subclass factoryMethod()ของผู้ปกครองที่มีกำหนดที่ นี่คือเหตุผลที่เราบอกว่าวิธีการใช้งานจากโรงงานถูกนำมาใช้โดยการสืบทอด
  2. จุดสำคัญที่สองคือการจำไว้ว่ารูปแบบวิธีการจากโรงงานไม่มีอะไรมากไปกว่าความเชี่ยวชาญของรูปแบบวิธีการของแม่แบบ ทั้งสองรูปแบบมีโครงสร้างที่เหมือนกัน พวกเขาแตกต่างกันในวัตถุประสงค์เท่านั้น วิธีการของโรงงานเป็นสิ่งที่สร้างสรรค์ (มันสร้างบางอย่าง) ในขณะที่วิธีแม่แบบนั้นเป็นพฤติกรรม
  3. และในที่สุดจุดที่สามที่จะต้องทราบก็คือว่าCreator(แม่) factoryMethod()ชั้นจะเรียกตัวของมันเอง หากเราลบออก anOperation()จากคลาสพาเรนต์โดยทิ้งเพียงวิธีเดียวไว้เบื้องหลังมันจะไม่อยู่ในรูปแบบวิธีการจากโรงงานอีกต่อไป กล่าวอีกนัยหนึ่งวิธีโรงงานไม่สามารถนำมาใช้กับน้อยกว่าสองวิธีในชั้นผู้ปกครอง; และอีกคนหนึ่งจะต้องเรียกคนอื่น
public abstract class Creator {
    public void anOperation() {
        Product p = factoryMethod();
        p.whatever();
    }

    protected abstract Product factoryMethod();
}

public class ConcreteCreator extends Creator {
    @Override
    protected Product factoryMethod() {
        return new ConcreteProduct();
    }
}

อื่น ๆ. และรูปแบบโรงงานต่างๆ

โปรดทราบว่าแม้ว่า GoF จะกำหนดรูปแบบโรงงานที่แตกต่างกันสองแบบ แต่สิ่งเหล่านี้ไม่ใช่รูปแบบของโรงงานเดียว พวกเขาไม่จำเป็นต้องเป็นรูปแบบของโรงงานที่ใช้กันมากที่สุด ตัวอย่างที่สามที่มีชื่อเสียงคือรูปแบบโรงงานคงที่ของ Josh Bloch จาก Java ที่มีประสิทธิภาพ หนังสือรูปแบบการออกแบบหัวแรกรวมถึงรูปแบบอื่นที่เรียกว่า Simple Factory

อย่าตกหลุมพรางของการสมมติว่าทุกรูปแบบของโรงงานจะต้องตรงกับรูปแบบจาก GoF


3
คำตอบที่ยอดเยี่ยมและชัดเจนมากตามตัวอย่างที่ดีคำตอบที่ดีที่สุดในหัวข้อนี้
ลุค Duda

คำอธิบายที่ดี +1 สำหรับวิธีการจากโรงงานจะต้องเรียกใช้จุดวิธีนามธรรมจากโรงงาน เมื่อมาถึงจุดนี้มันชัดเจนมากโดยไม่เข้าใจประเด็นนี้: ถ้าเรามีวิธีการที่โรงงานไม่ได้ถูกเรียกใช้โดยตัวมันเองก็หมายความว่ามันจะถูกใช้โดยชั้นเรียนอื่น ๆ ที่จะเขียนมันและชั้นย่อยจะถูกฉีดเข้าไป ความแตกต่างจะชัดเจนน้อยลงถ้าจุดที่โรงงานนามธรรมต้องเรียกใช้โดยตัวโรงงานเองเช่นรูปแบบแม่แบบไม่เข้าใจ
nits.kk

อีกหนึ่งคำถามคำพูด ควรfactoryMethod()เป็นprotected วิธีในรูปแบบ "วิธีการจากโรงงาน" เสมอหรือไม่ (ฉันคิดว่าใช่)
Yaroslav Fedoruk

1
@YaroslavFedoruk หนังสือ GoF ช่วยให้publicวิธีการของโรงงานและวิธีการที่ไม่จำเป็นต้องแม้แต่abstract; แต่จุดสำคัญคือวิธีการที่มีไว้สำหรับมรดกดังนั้นจึงไม่สามารถ (ตัวอย่าง) เป็นได้ทั้งหรือstatic finalฉันได้ทำวิธีprotectedและabstractที่นี่เพื่อเน้นการขยาย (จำเป็น)
jaco0646

@ nits.kk คุณอาจจะสนใจในคำตอบที่เกี่ยวข้อง
jaco0646

26

Abstract Factory เป็นอินเทอร์เฟซสำหรับสร้างผลิตภัณฑ์ที่เกี่ยวข้อง แต่วิธีการจากโรงงานเป็นเพียงวิธีเดียว บทคัดย่อโรงงานสามารถนำไปใช้ได้หลายวิธี

บทคัดย่อโรงงาน UML


10
คุณได้โพสต์แล้วคำตอบเดียวกันที่นี่ หากคุณรู้สึกว่าคำถามนี้คล้ายกันให้ตั้งค่าสถานะว่าซ้ำกัน
ก.ค.

11

พิจารณาตัวอย่างนี้เพื่อความเข้าใจง่าย

บริษัท โทรคมนาคมให้บริการอะไร? ยกตัวอย่างเช่นบรอดแบนด์สายโทรศัพท์และมือถือและคุณจะถูกขอให้สร้างแอปพลิเคชันเพื่อเสนอผลิตภัณฑ์ให้กับลูกค้าของพวกเขา

โดยทั่วไปสิ่งที่คุณทำที่นี่คือการสร้างผลิตภัณฑ์เช่นบรอดแบนด์สายโทรศัพท์และมือถือผ่านวิธีการของโรงงานซึ่งคุณรู้ว่าคุณสมบัติใดที่คุณมีสำหรับผลิตภัณฑ์เหล่านั้นและมันค่อนข้างตรงไปตรงมา

ตอนนี้ บริษัท ต้องการที่จะให้ลูกค้าของพวกเขาเป็นกลุ่มของผลิตภัณฑ์ของพวกเขาเช่นบรอดแบนด์, สายโทรศัพท์และโทรศัพท์มือถือทั้งหมดและนี่มาบทคัดย่อโรงงานที่จะเล่น

ในคำอื่น ๆบทคัดย่อเป็นองค์ประกอบของโรงงานอื่น ๆ ที่มีหน้าที่รับผิดชอบในการสร้างผลิตภัณฑ์ของตนเองและบทคัดย่อโรงงานรู้วิธีการวางผลิตภัณฑ์เหล่านี้มีความหมายมากขึ้นในแง่ของความรับผิดชอบของตนเอง

ในกรณีนี้BundleFactoryเป็นโรงงานนามธรรมBroadbandFactory, PhonelineFactoryและเป็นMobileFactory Factoryเพื่อให้ง่ายขึ้นโรงงานเหล่านี้จะมีวิธีการเริ่มต้นจากแต่ละผลิตภัณฑ์

ดูตัวอย่างรหัสด้านล่าง:

public class BroadbandFactory : IFactory {
    public static Broadband CreateStandardInstance() {
        // broadband product creation logic goes here
    }
}

public class PhonelineFactory : IFactory {
    public static Phoneline CreateStandardInstance() {
        // phoneline product creation logic goes here
    }
}

public class MobileFactory : IFactory {
    public static Mobile CreateStandardInstance() {
        // mobile product creation logic goes here
    }
}

public class BundleFactory : IAbstractFactory {

    public static Bundle CreateBundle() {
        broadband = BroadbandFactory.CreateStandardInstance();
        phoneline = PhonelineFactory.CreateStandardInstance();
        mobile = MobileFactory.CreateStandardInstance();

        applySomeDiscountOrWhatever(broadband, phoneline, mobile);
    }

    private static void applySomeDiscountOrWhatever(Broadband bb, Phoneline pl, Mobile m) {
        // some logic here
        // maybe manange some variables and invoke some other methods/services/etc.
    }
}

หวังว่านี่จะช่วยได้


1
ไม่มีstaticวิธีการในรูปแบบของโรงงาน GoF นี่เป็นสิ่งที่ผิด
jaco0646

5

ตัวอย่างชีวิตจริง (จำง่าย)

โรงงาน

ลองนึกภาพคุณกำลังสร้างบ้านและคุณเข้าใกล้ช่างไม้สำหรับประตู คุณให้การวัดสำหรับประตูและความต้องการของคุณและเขาจะสร้างประตูให้คุณ ในกรณีนี้ช่างไม้เป็นโรงงานประตู ข้อมูลจำเพาะของคุณเป็นอินพุตสำหรับโรงงานและประตูเป็นเอาต์พุตหรือผลิตภัณฑ์จากโรงงาน

โรงงานบทคัดย่อ

ตอนนี้ลองพิจารณาตัวอย่างเดียวกันของประตู คุณสามารถไปที่ช่างไม้หรือไปที่ร้านขายประตูพลาสติกหรือร้านพีวีซี พวกเขาทั้งหมดเป็นโรงงานประตู ขึ้นอยู่กับสถานการณ์คุณตัดสินใจประเภทของโรงงานที่คุณต้องเข้าใกล้ นี่เป็นเหมือนโรงงานนามธรรม

ฉันได้อธิบายที่นี่ทั้งรูปแบบวิธีการในโรงงานและรูปแบบนามธรรมจากโรงงานโดยไม่ใช้พวกเขาอธิบายปัญหาและจากนั้นจึงแก้ปัญหาโดยใช้รูปแบบข้างต้น https://github.com/vikramnagineni/Design-Patterns/tree/master


3

ให้เราอธิบายอย่างชัดเจนว่าส่วนใหญ่ในรหัสการผลิตเราใช้รูปแบบโรงงานที่เป็นนามธรรมเพราะคลาส A ถูกตั้งโปรแกรมด้วยอินเตอร์เฟส B และ A จำเป็นต้องสร้างอินสแตนซ์ของ B ดังนั้น A ต้องมีวัตถุโรงงานเพื่อสร้างอินสแตนซ์ของ B ดังนั้น A ไม่ได้ขึ้นอยู่กับตัวอย่างที่เป็นรูปธรรมของ B. หวังว่าจะช่วยได้


3

ทำความเข้าใจกับความแตกต่างในแรงจูงใจ:

สมมติว่าคุณกำลังสร้างเครื่องมือที่คุณมีวัตถุและการประยุกต์ใช้ความสัมพันธ์ของวัตถุอย่างเป็นรูปธรรม เมื่อคุณมองเห็นความแปรปรวนในวัตถุคุณได้สร้างทางอ้อมโดยมอบหมายความรับผิดชอบในการสร้างรูปแบบของวัตถุให้กับวัตถุอื่น ( เราเรียกมันว่าเป็นนามธรรมจากโรงงาน ) สิ่งที่เป็นนามธรรมนี้พบว่ามีประโยชน์มากเนื่องจากคุณคาดการณ์ว่าส่วนขยายในอนาคตที่ต้องการตัวแปรของวัตถุเหล่านั้น

แรงจูงใจที่น่าสนใจอีกอย่างในแนวความคิดนี้คือกรณีที่วัตถุทุกชิ้นหรือไม่มีจากกลุ่มทั้งหมดจะมีตัวแปรที่สอดคล้องกัน ขึ้นอยู่กับเงื่อนไขบางอย่างตัวแปรตัวใดตัวหนึ่งจะถูกนำมาใช้และในแต่ละกรณีวัตถุทั้งหมดจะต้องมีตัวแปรเดียวกัน นี้อาจจะมีบิตเคาน์เตอร์ง่ายที่จะเข้าใจที่เรามักจะมีแนวโน้มคิดว่า - ตราบใดที่สายพันธุ์ของวัตถุตามสัญญาเครื่องแบบที่พบบ่อย ( อินเตอร์เฟซในความหมายกว้าง ) รหัสการใช้งานคอนกรีตไม่ควรทำลาย ข้อเท็จจริงที่น่าสนใจที่นี่ก็คือไม่ได้เป็นเช่นนี้เสมอไปโดยเฉพาะอย่างยิ่งเมื่อพฤติกรรมที่คาดหวังไม่สามารถสร้างแบบจำลองโดยสัญญาการเขียนโปรแกรม

ง่าย ๆ ( ยืมความคิดจาก GoF ) คือแอปพลิเคชัน GUI ใด ๆ ที่บอกว่าจอภาพเสมือนที่เลียนแบบลุคของ MS หรือ Mac หรือ Fedora OS ตัวอย่างเช่นที่นี่เมื่อวัตถุวิดเจ็ตทั้งหมดเช่นหน้าต่างปุ่ม ฯลฯ มีตัวแปร MS ยกเว้นแถบเลื่อนที่ได้มาจากตัวแปร MAC วัตถุประสงค์ของเครื่องมือล้มเหลวอย่างรุนแรง

กรณีข้างต้นเหล่านี้ในรูปแบบความต้องการพื้นฐานของรูปแบบโรงงานบทคัดย่อ

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

หมายเหตุน้อย:

  • หากคุณคุ้นเคยกับ 'วิธีการเทมเพลต' คุณจะเห็นว่าวิธีการจากโรงงานมักถูกเรียกใช้จากวิธีการเทมเพลตในกรณีที่โปรแกรมที่เกี่ยวข้องกับเฟรมเวิร์กรูปแบบใด ๆ ในทางตรงกันข้ามวิธีแม่แบบของแอปพลิเคชันโปรแกรมมักจะใช้งานง่ายของอัลกอริทึมเฉพาะและโมฆะของวิธีการโรงงาน
  • นอกจากนี้เพื่อความสมบูรณ์ของความคิดโดยใช้กรอบงาน ( ดังกล่าวข้างต้น ) เมื่อผู้สร้างเครื่องมือกำลังสร้างเครื่องมือภายในแต่ละวิธีโรงงานแทนที่จะสร้างวัตถุที่เป็นรูปธรรมเขา / เธออาจมอบหมายความรับผิดชอบต่อนามธรรม - โรงงานวัตถุให้เครื่องมือสร้างเล็งเห็นการเปลี่ยนแปลงของวัตถุที่เป็นรูปธรรมสำหรับส่วนขยายในอนาคต

รหัสตัวอย่าง:

//Part of framework-code
BoardGame {
    Board createBoard() //factory method. Default implementation can be provided as well
    Piece createPiece() //factory method

    startGame(){        //template method
         Board borad = createBoard()
         Piece piece = createPiece()
         initState(board, piece)
    }
}


//Part of Tool-builder code
Ludo inherits  BoardGame {
     Board createBoard(){ //overriding of factory method
         //Option A: return new LudoBoard() //Lodu knows object creation
         //Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
     }
….
}

//Part of Tool-builder code
Chess inherits  BoardGame {
    Board createBoard(){ //overriding of factory method
        //return a Chess board
    }
    ….
}

3
  1. คำถามแรกของฉันเกี่ยวกับโรงงานที่เป็นนามธรรม บทบาทของมันคือการอนุญาตให้คุณสร้างตระกูลของวัตถุที่เป็นรูปธรรมใน (ซึ่งสามารถขึ้นอยู่กับโรงงานที่คุณใช้เฉพาะ) แทนที่จะเป็นวัตถุรูปธรรมเดียวหรือไม่

ใช่. เจตนาของ Abstract Factory คือ:

จัดเตรียมส่วนต่อประสานสำหรับการสร้างตระกูลของวัตถุที่เกี่ยวข้องหรือวัตถุที่ต้องพึ่งพาโดยไม่ต้องระบุคลาสที่เป็นรูปธรรม


  1. โรงงานนามธรรมส่งคืนวัตถุที่มีขนาดใหญ่มากหรือวัตถุจำนวนมากขึ้นอยู่กับวิธีการที่คุณเรียกใช้หรือไม่

โดยหลักการแล้วมันควรจะคืนค่าหนึ่งอ๊อบเจคหนึ่งต่อเมธอดไคลเอ็นต์ที่เรียกใช้

  1. ความเข้าใจของฉันคือรูปแบบวิธีการของโรงงานมีส่วนต่อประสานผู้สร้างที่จะทำให้ ConcreteCreator รับผิดชอบในการทราบว่า ConcreteProduct ใดที่จะยกตัวอย่าง นี่คือความหมายของการใช้การสืบทอดเพื่อจัดการการสร้างอินสแตนซ์ของวัตถุหรือไม่

ใช่. วิธีการจากโรงงานใช้การสืบทอด

  1. บทคัดย่อรูปแบบโรงงานมอบหมายความรับผิดชอบในการสร้างอินสแตนซ์ของวัตถุไปยังวัตถุอื่นผ่านการจัดองค์ประกอบ? สิ่งนี้หมายความว่า?

AbstractFactory กำหนด FactoryMethod และ ConcreteFactory เป็นผู้รับผิดชอบในการสร้างผลิตภัณฑ์คอนกรีต เพียงทำตามผ่านตัวอย่างรหัสที่อยู่ในนี้ บทความ

คุณสามารถค้นหารายละเอียดเพิ่มเติมในโพสต์ SE ที่เกี่ยวข้อง:

ความแตกต่างพื้นฐานระหว่างรูปแบบโรงงานและนามธรรมเป็นอย่างไร

รูปแบบการออกแบบ: โรงงานกับวิธีการของโรงงานเทียบกับบทคัดย่อจากโรงงาน


3

วิธีการของโรงงานอาศัยการสืบทอด: การสร้างวัตถุจะมอบให้กับคลาสย่อยซึ่งใช้วิธีการจากโรงงานเพื่อสร้างวัตถุ

บทคัดย่อโรงงานพึ่งพาองค์ประกอบของวัตถุ: การสร้างวัตถุถูกนำไปใช้ในวิธีการที่เปิดเผยในส่วนต่อประสานโรงงาน

แผนภาพระดับสูงของโรงงานและรูปแบบโรงงานนามธรรม

แผนภาพ

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการโรงงานโปรดดูบทความนี้

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการโรงงานบทคัดย่อโปรดดูบทความนี้


2

เพื่อให้ง่ายมากด้วยอินเทอร์เฟซขั้นต่ำ & โปรดโฟกัส "// 1":

class FactoryProgram
    {
        static void Main()
        {
            object myType = Program.MyFactory("byte");
            Console.WriteLine(myType.GetType().Name);

            myType = Program.MyFactory("float"); //3
            Console.WriteLine(myType.GetType().Name);

            Console.ReadKey();
        }

        static object MyFactory(string typeName)
        {
            object desiredType = null; //1
            switch (typeName)
            {
                case "byte": desiredType = new System.Byte(); break; //2
                case "long": desiredType = new System.Int64(); break;
                case "float": desiredType = new System.Single(); break;
                default: throw new System.NotImplementedException();
            }
            return desiredType;
        }
    }

ประเด็นสำคัญที่นี่: 1. กลไกการทำงานของโรงงานและ AbstractFactory ต้องใช้การสืบทอด (System.Object-> byte, float ... ); ดังนั้นหากคุณมีการสืบทอดในโปรแกรมดังนั้น Factory (Abstract Factory จะไม่อยู่ที่นั่น) โดยการออกแบบ 2. ผู้สร้าง (MyFactory) รู้เกี่ยวกับประเภทคอนกรีตดังนั้นส่งคืนวัตถุประเภทคอนกรีตไปยังผู้โทร (หลัก); ในประเภทโรงงานคืนนามธรรมจะเป็นอินเตอร์เฟซ

interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
    {
        IVehicle CreateSingleVehicle(string vehicleType);
    }
class HondaFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports": return new SportsBike();
                case "Regular":return new RegularBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }
class HeroFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports":  return new SportsBike();
                case "Scooty": return new Scooty();
                case "DarkHorse":return new DarkHorseBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }

class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }

class Program
{
    static void Main(string[] args)
    {
        IVehicleFactory honda = new HondaFactory(); //1
        RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
        SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
        Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);

        IVehicleFactory hero = new HeroFactory();
        DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
        SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
        Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
        Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);

        Console.ReadKey();
    }
}

จุดสำคัญ: 1. ข้อกำหนด: ฮอนด้าจะสร้าง "ปกติ", "กีฬา" แต่ฮีโร่จะสร้าง "DarkHorse", "Sports" และ "Scooty" 2. ทำไมต้องมีสองอินเตอร์เฟส? หนึ่งสำหรับประเภทผู้ผลิต (IVehicleFactory) และอีกหนึ่งสำหรับโรงงานผลิตภัณฑ์ (IVehicle); วิธีอื่นในการทำความเข้าใจ 2 อินเตอร์เฟสคือโรงงานนามธรรมคือทั้งหมดที่เกี่ยวกับการสร้างวัตถุที่เกี่ยวข้อง 2. สิ่งที่จับได้คือลูกของ IVehicleFactory ที่กลับมาและ IVehicle (แทนที่จะเป็นรูปธรรมในโรงงาน); ดังนั้นฉันจึงได้รับตัวแปรผู้ปกครอง (IVehicle); จากนั้นฉันสร้างชนิดคอนกรีตจริงโดยการเรียก CreateSingleVehicle แล้วหล่อวัตถุหลักไปยังวัตถุลูกที่แท้จริง จะเกิดอะไรขึ้นถ้าฉันทำRegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");; คุณจะได้รับ ApplicationException และนั่นคือเหตุผลที่เราต้องการโรงงานนามธรรมทั่วไปซึ่งฉันจะอธิบายหากจำเป็น


1

โรงงานบทคัดย่อ : โรงงานของโรงงาน โรงงานที่จัดกลุ่มบุคคล แต่เกี่ยวข้อง / ขึ้นอยู่กับโรงงานด้วยกันโดยไม่ต้องระบุชั้นเรียนที่เป็นรูปธรรม ตัวอย่างโรงงานบทคัดย่อ

โรงงาน : มันมีวิธีในการมอบหมายตรรกะการสร้างอินสแตนซ์ให้กับคลาสเด็ก ตัวอย่างรูปแบบโรงงาน


0

ฉันจะชอบบทคัดย่อโรงงานมากกว่าวิธีการโรงงานได้ตลอดเวลา จากตัวอย่างของ Tom Dalling (คำอธิบายที่ดีมาก btw) ด้านบนเราจะเห็นได้ว่า Abstract Factory มีความหลากหลายมากขึ้นในสิ่งที่เราต้องทำคือการส่งโรงงานที่แตกต่างไปยังตัวสร้าง แต่วิธีการจากโรงงานต้องการให้เราแนะนำคลาสใหม่ (มีสิ่งเพิ่มเติมให้จัดการ) และใช้คลาสย่อย ชอบองค์ประกอบมากกว่ามรดกเสมอ


0

อนุญาตให้ฉันใส่มันอย่างแม่นยำ คำตอบส่วนใหญ่ได้อธิบายไปแล้วจัดเตรียมไดอะแกรมและตัวอย่างไว้ด้วย ดังนั้น anwer ของฉันก็จะเป็นหนึ่งซับ คำพูดของฉัน: - “ รูปแบบโรงงานที่เป็นนามธรรมเพิ่มในเลเยอร์นามธรรมผ่านการใช้วิธีการที่หลากหลายจากโรงงาน หมายถึงโรงงานนามธรรมมีหรือประกอบหนึ่งหรือมากกว่าหนึ่งรูปแบบวิธีการโรงงาน”


สิ่งนี้ไม่ถูกต้อง นี่เป็นความเข้าใจผิดที่เกิดขึ้นบ่อยเกินไปที่บทคัดย่อโรงงานไม่มีอะไรมากไปกว่าโรงงานในโรงงาน
jaco0646

0

คำตอบข้างต้นจำนวนมากไม่ได้ให้การเปรียบเทียบรหัสระหว่างรูปแบบนามธรรมจากโรงงานและวิธีการของโรงงาน ต่อไปนี้เป็นความพยายามของฉันในการอธิบายผ่านทาง Java หวังว่าจะช่วยคนที่ต้องการคำอธิบายง่ายๆ

ในฐานะที่เป็น GoF เหมาะเจาะพูดว่า: บทคัดย่อโรงงานให้อินเตอร์เฟซสำหรับการสร้างครอบครัวของวัตถุที่เกี่ยวข้องหรือขึ้นอยู่กับโดยไม่ต้องระบุชั้นคอนกรีตของพวกเขา

        public class Client {
            public static void main(String[] args) {
               ZooFactory zooFactory = new HerbivoreZooFactory();       
               Animal animal1 = zooFactory.animal1();
               Animal animal2 = zooFactory.animal2();
               animal1.sound();
               animal2.sound();

               System.out.println();

               AnimalFactory animalFactory = new CowAnimalFactory();
               Animal animal = animalFactory.createAnimal();
               animal.sound();
            }
        }

        public interface Animal {
            public void sound();
        }

        public class Cow implements Animal {

            @Override
            public void sound() {
                System.out.println("Cow moos");
            }

        }

        public class Deer implements Animal {

            @Override
            public void sound() {
                System.out.println("Deer grunts");
            }

        }

        public class Hyena implements Animal {

            @Override
            public void sound() {
                System.out.println("Hyena.java");
            }

        }

        public class Lion implements Animal {

            @Override
            public void sound() {
                System.out.println("Lion roars");
            }

        }

        public interface ZooFactory {
            Animal animal1();

            Animal animal2();
        }

        public class CarnivoreZooFactory implements ZooFactory {

            @Override
            public Animal animal1() {
                return new Lion();
            }

            @Override
            public Animal animal2() {
                return new Hyena();
            }

        }

        public class HerbivoreZooFactory implements ZooFactory{

            @Override
            public Animal animal1() {
                return new Cow();
            }

            @Override
            public Animal animal2() {
                return new Deer();
            }

        }

        public interface AnimalFactory {
            public Animal createAnimal();
        }

        public class CowAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Cow();
            }

        }

        public class DeerAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Deer();
            }

        }

        public class HyenaAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Hyena();
            }

        }

        public class LionAnimalFactory implements AnimalFactory{

            @Override
            public Animal createAnimal() {
                return new Lion();
            }

        }

สิ่งนี้ไม่ถูกต้อง รหัสนี้ใช้ความเข้าใจผิดที่เกิดขึ้นบ่อยเกินไปที่บทคัดย่อโรงงานไม่มีอะไรมากไปกว่าโรงงานในโรงงาน
jaco0646

1
@ jaco0646 ฉันเชื่อว่าในรูปแบบวิธีการของโรงงานให้ความสำคัญกับการดึงผลิตภัณฑ์คอนกรีตเพียงชิ้นเดียวออกจาก FactoryImpl ในขณะที่ในรูปแบบโรงงานที่เป็นนามธรรม FactoryImpls มีหน้าที่รับผิดชอบในการจัดหาผลิตภัณฑ์คอนกรีตที่คล้ายกัน / เกี่ยวข้องหลายรายการซึ่งอินเตอร์เฟสโรงงานจัดทำสัญญา ดังนั้น ZooFactory จึงไม่ใช่โรงงานของโรงงานอย่างที่คุณพูด แต่เป็นเพียงส่วนต่อประสานที่ Impls จัดหาผลิตภัณฑ์คอนกรีตที่เกี่ยวข้องกัน อย่าลังเลที่จะแก้ไขความเข้าใจของฉันถ้าคุณไม่เห็นด้วย
Jatin Shashoo

ในวิธีการของโรงงานให้ความสำคัญกับการสืบทอดผ่านการจัดกลุ่มย่อยเนื่องจากวิธีการของโรงงานเป็นความเชี่ยวชาญเฉพาะของรูปแบบวิธีการของแม่แบบ คำตอบที่ได้รับคะแนนสูงสุดด้านบนแสดงตัวอย่างรหัสที่เหมาะสม
jaco0646

@ jaco0646 1. นี่หมายความว่าในตัวอย่างข้างต้นแทนที่จะใช้อินเตอร์เฟสสำหรับ AnimalFactory และให้การใช้งานของมันฉันควรจะใช้คลาสและแทนที่เมธอด createAnimal () ในคลาสย่อย: CowAnimalFactory, LionAnimalFactory, etc? 2. อะไรคือความคิดของคุณเกี่ยวกับตัวอย่างที่แสดงสำหรับ ZooFactory
Jatin Shashoo

สำหรับคำถามแรก: ใช่ ในตอนที่สองฉันได้เพิ่มคำตอบของตัวเองในหัวข้อนี้แทนที่จะทำการวิจารณ์คำตอบของแต่ละคนต่อไป
jaco0646
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.