รูปแบบโรงงาน จะใช้วิธีการจากโรงงานเมื่อใด


คำตอบ:


386

ฉันชอบคิดเกี่ยวกับการออกแบบเสื้อในแง่ของชั้นเรียนของฉันเป็น 'คน' และรูปแบบเป็นวิธีที่ผู้คนพูดคุยกัน

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

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

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

public interface IThingFactory
{
    Thing GetThing(string theString);
}

public class ThingFactory : IThingFactory
{
    public Thing GetThing(string theString)
    {
        return new Thing(theString, firstDependency, secondDependency);
    }
}

ดังนั้นตอนนี้ผู้บริโภคของ ThingFactory สามารถได้รับ Thing โดยไม่ต้องรู้เกี่ยวกับการพึ่งพาของ Thing ยกเว้นข้อมูลสตริงที่มาจากผู้บริโภค


17
การใช้งานที่เป็นรูปธรรมของ GetThing () ดึงค่าของ firstDependency และ secondDependency ที่ใด
Mikeyg36

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

4
คำถาม OP within an object instead of a Factory classกล่าวถึงอย่างชัดเจน ฉันคิดว่าเขาหมายถึงสถานการณ์ที่คุณทำให้ ctor เป็นส่วนตัวและใช้วิธีการคงที่เพื่อยกตัวอย่างชั้นเรียน (สร้างวัตถุ) แต่ในการทำตามตัวอย่างนี้เราต้องยกตัวอย่างThingFactoryคลาสก่อนเพื่อให้ได้Thingวัตถุซึ่งทำให้สิ่งนี้มีFactory classผล
atiyar

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

8
OP ถามเมื่อ Kyoryu ตอบว่า แม้ว่ารูปแบบของคำตอบน่ายกย่อง แต่ในบริบทของคำถามนี้มันเป็นเพียงแค่เสียงรบกวน
8bitjunkie

96

วิธีการในโรงงานควรได้รับการพิจารณาว่าเป็นทางเลือกสำหรับช่างก่อสร้าง

class Foo{
  public Foo(bool withBar);
}

ไม่แสดงออกอย่างที่:

class Foo{
  public static Foo withBar();
  public static Foo withoutBar();
}

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


2
คลาส Factory อยู่ที่นี่ที่ไหน
Koray Tugay

20
@KorayTugay: ไม่มีคลาสโรงงานเพียงวิธีการของโรงงาน คำถามนี้เกี่ยวกับเวลาที่จะใช้วิธีการของโรงงานแทนที่จะเป็นระดับโรงงาน แต่วิธีการในโรงงานเป็นทางเลือกให้กับผู้สร้างมากกว่าทางเลือกอื่นสำหรับคลาสโรงงาน (ฉันไม่รู้ว่าทำไมคำตอบยอดนิยมถึงได้รับการจัดอันดับสูงมากแม้จะพูดถึงชั้นเรียนของโรงงานเท่านั้น)
Rasmus Faber

5
ควรสังเกตว่าวิธีการของโรงงานแบบคงที่นั้นแตกต่างจากรูปแบบการออกแบบ Gang of Four อย่างสิ้นเชิง:
jaco0646

76

สถานการณ์หนึ่งที่ฉันค้นหาคลาส Factory แบบแยกต่างหากเพื่อให้เข้าใจได้ง่ายคือเมื่อวัตถุสุดท้ายที่คุณพยายามสร้างนั้นใช้วัตถุอื่นหลายตัว เช่นใน PHP: สมมติว่าคุณมีHouseวัตถุซึ่งจะมีKitchenและLivingRoomวัตถุและLivingRoomวัตถุมีTVวัตถุอยู่ภายในเช่นกัน

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

ทางเลือกคือทำสิ่งต่อไปนี้ (การฉีดพึ่งพาหากคุณชอบเทอมแฟนซี):

$TVObj = new TV($param1, $param2, $param3);
$LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
$KitchenroomObj = new Kitchen($param1, $param2);
$HouseObj = new House($LivingroomObj, $KitchenroomObj);

ที่นี่หากกระบวนการสร้างความHouseล้มเหลวมีเพียงที่เดียวที่จะมอง แต่ต้องใช้อันนี้ทุกครั้งที่ต้องการใหม่Houseอยู่ไกลจากความสะดวกสบาย เข้าสู่โรงงาน:

class HouseFactory {
    public function create() {
        $TVObj = new TV($param1, $param2, $param3);
        $LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
        $KitchenroomObj = new Kitchen($param1, $param2);
        $HouseObj = new House($LivingroomObj, $KitchenroomObj);

        return $HouseObj;
    }
}

$houseFactory = new HouseFactory();
$HouseObj = $houseFactory->create();

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


1
บางคนจะทำการทดสอบหน่วยในเรื่องนี้อย่างไร ฉันคิดว่าการใช้คำหลัก "ใหม่" ในชั้นเรียนถือว่าเป็นการฝึกที่ไม่ดีเพราะไม่สามารถทดสอบหน่วยได้ หรือว่าโรงงานมีข้อยกเว้นเล็กน้อยสำหรับกฎนั้น
AgmLauncher

1
@ AgmLauncher ฉันมีคำถามเดียวกันเช่นกันเมื่อฉันเริ่มต้นด้วยการทดสอบหน่วยตรวจสอบ: stackoverflow.com/questions/10128780/…
Mahn

1
ไม่ได้รับสิ่งนี้ พารามิเตอร์สำหรับการสร้างวัตถุต่าง ๆ นั้นถูกส่งผ่านไปยังHouseFactoryชั้นเรียนได้อย่างไร?
atiyar

1
@Mahn คุณจะไม่จบลงด้วยการมี params มากมายในตอนท้ายหรือไม่?
Pacerier

1
@Pacerier ว่าบางสิ่งบางอย่างสำหรับคุณที่จะตัดสินใจว่าจะรูปแบบขึ้นอยู่กับความต้องการของคุณ แต่คุณไม่ได้มักจะต้องผ่านทุกพารามิเตอร์กับcreateวิธีการ เช่นถ้าคุณHouseจะมีประเภทเดียวกันอยู่ตลอดเวลาLivingRoomมันอาจสมเหตุสมผลที่จะมี params hardcoded ในคลาสโรงงานแทนที่จะส่งผ่านเป็นอาร์กิวเมนต์ หรือคุณอาจต้องการที่จะให้typeข้อโต้แย้งกับHouseFactory::createวิธีการของคุณหากคุณมีสองสามชนิดLivingRoomและมีสวิตช์ภายในพร้อมพารามิเตอร์ hardcoded สำหรับแต่ละประเภท
Mahn

19

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

ขอเจาะจงเกี่ยวกับ "วิธีการจากโรงงาน":

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

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

interface Deliverable 
{
    /*********/
}

abstract class DefaultProducer 
{

    public void taskToBeDone() 
    {   
        Deliverable deliverable = factoryMethodPattern();
    }
    protected abstract Deliverable factoryMethodPattern();
}

class SpecificDeliverable implements Deliverable 
{
 /***SPECIFIC TASK CAN BE WRITTEN HERE***/
}

class SpecificProducer extends DefaultProducer 
{
    protected Deliverable factoryMethodPattern() 
    {
        return new SpecificDeliverable();
    }
}

public class MasterApplicationProgram 
{
    public static void main(String arg[]) 
    {
        DefaultProducer defaultProducer = new SpecificProducer();
        defaultProducer.taskToBeDone();
    }
}

15

พวกมันยังมีประโยชน์เมื่อคุณต้องการ "constructors" หลายตัวที่มีพารามิเตอร์ชนิดเดียวกัน แต่มีพฤติกรรมแตกต่างกัน


15

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

  1. คลาสของออบเจ็กต์ไม่รู้ว่าต้องสร้างคลาสย่อยอะไร
  2. คลาสของวัตถุนั้นถูกออกแบบมาเพื่อให้วัตถุที่มันสร้างนั้นถูกระบุโดยคลาสย่อย
  3. คลาสของ Object มอบหมายหน้าที่ให้กับคลาสย่อยเสริมและไม่ทราบว่าคลาสใดที่แน่นอนจะทำหน้าที่เหล่านี้

เป็นความคิดที่ดีที่จะใช้คลาสโรงงานที่เป็นนามธรรมเมื่อ:

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

9

UML จาก

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

ผลิตภัณฑ์:กำหนดอินเทอร์เฟซของวัตถุที่วิธีการสร้างจากโรงงาน

ผลิตภัณฑ์คอนกรีต:ใช้ส่วนต่อประสานผลิตภัณฑ์

ผู้สร้าง:ประกาศวิธีการของโรงงาน

ConcreateCreator: ใช้เมธอด Factory เพื่อส่งคืนอินสแตนซ์ของ ConcreteProduct

ข้อความแจ้งปัญหา:สร้าง Factory of Games โดยใช้ Factory Methods ซึ่งเป็นตัวกำหนดส่วนต่อประสานเกม

ข้อมูลโค้ด:

import java.util.HashMap;


/* Product interface as per UML diagram */
interface Game{
    /* createGame is a complex method, which executes a sequence of game steps */
    public void createGame();
}

/* ConcreteProduct implementation as per UML diagram */
class Chess implements Game{
    public Chess(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Chess game");
        System.out.println("Opponents:2");
        System.out.println("Define 64 blocks");
        System.out.println("Place 16 pieces for White opponent");
        System.out.println("Place 16 pieces for Black opponent");
        System.out.println("Start Chess game");
        System.out.println("---------------------------------------");
    }
}
class Checkers implements Game{
    public Checkers(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Checkers game");
        System.out.println("Opponents:2 or 3 or 4 or 6");
        System.out.println("For each opponent, place 10 coins");
        System.out.println("Start Checkers game");
        System.out.println("---------------------------------------");
    }
}
class Ludo implements Game{
    public Ludo(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Ludo game");
        System.out.println("Opponents:2 or 3 or 4");
        System.out.println("For each opponent, place 4 coins");
        System.out.println("Create two dices with numbers from 1-6");
        System.out.println("Start Ludo game");
        System.out.println("---------------------------------------");
    }
}

/* Creator interface as per UML diagram */
interface IGameFactory {
    public Game getGame(String gameName);
}

/* ConcreteCreator implementation as per UML diagram */
class GameFactory implements IGameFactory {

     HashMap<String,Game> games = new HashMap<String,Game>();
    /*  
        Since Game Creation is complex process, we don't want to create game using new operator every time.
        Instead we create Game only once and store it in Factory. When client request a specific game, 
        Game object is returned from Factory instead of creating new Game on the fly, which is time consuming
    */

    public GameFactory(){

        games.put(Chess.class.getName(),new Chess());
        games.put(Checkers.class.getName(),new Checkers());
        games.put(Ludo.class.getName(),new Ludo());        
    }
    public Game getGame(String gameName){
        return games.get(gameName);
    }
}

public class NonStaticFactoryDemo{
    public static void main(String args[]){
        if ( args.length < 1){
            System.out.println("Usage: java FactoryDemo gameName");
            return;
        }

        GameFactory factory = new GameFactory();
        Game game = factory.getGame(args[0]);
        if ( game != null ){                    
            game.createGame();
            System.out.println("Game="+game.getClass().getName());
        }else{
            System.out.println(args[0]+  " Game does not exists in factory");
        }           
    }
}

เอาท์พุท:

java NonStaticFactoryDemo Chess
---------------------------------------
Create Chess game
Opponents:2
Define 64 blocks
Place 16 pieces for White opponent
Place 16 pieces for Black opponent
Start Chess game
---------------------------------------
Game=Chess

ตัวอย่างนี้แสดงให้เห็นถึงระดับโดยการใช้FactoryFactoryMethod

  1. Gameเป็นอินเทอร์เฟซสำหรับเกมทุกประเภท มันกำหนดวิธีการที่ซับซ้อน:createGame()

  2. Chess, Ludo, Checkers เป็นรูปแบบที่แตกต่างกันของเกมซึ่งมีการใช้ createGame()

  3. public Game getGame(String gameName)อยู่FactoryMethodในIGameFactoryชั้นเรียน

  4. GameFactoryสร้างเกมประเภทต่างๆในตัวสร้างล่วงหน้า ใช้IGameFactoryวิธีการจากโรงงาน

  5. ชื่อเกมถูกส่งผ่านเป็นอาร์กิวเมนต์บรรทัดคำสั่งไปที่ NotStaticFactoryDemo

  6. getGameในGameFactoryยอมรับชื่อเกมและส่งกลับGameวัตถุที่สอดคล้องกัน

โรงงาน:

สร้างวัตถุโดยไม่ต้องเปิดเผยตรรกะการสร้างอินสแตนซ์ไปยังลูกค้า

FactoryMethod

กำหนดอินเทอร์เฟซสำหรับการสร้างวัตถุ แต่ให้คลาสย่อยตัดสินใจว่าคลาสใดที่จะยกตัวอย่าง เมธอด Factory อนุญาตให้คลาสเลื่อนการอินสแตนซ์ไปที่คลาสย่อย

ใช้กรณี:

ควรใช้เมื่อClientใด: ไม่ทราบว่าจะต้องสร้างคลาสที่เป็นรูปธรรมเมื่อใด แต่ต้องมีคลาสที่จะทำงาน


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

getArea()ไม่ได้เป็นวิธีการที่โรงงานที่ทั้งหมด
Cranio

1
ฉันมีความคิดเห็นที่แตกต่าง - ผู้เชี่ยวชาญโปรดตรวจสอบและใส่บันทึก 1. ไคลเอนต์ (หรือผู้เรียก) ต้องการวัตถุที่น่าสนใจ ... ดังนั้นจึงไม่จำเป็นต้องเรียกGameFactory ใหม่ ()ค่อนข้างคลาสโรงงานควรมี getInstance แบบคงที่ () 2.Also ถ้าเป็นเช่นนั้นแล้ว game.put (Chess.class.getName ( ), หมากรุกใหม่ ()); จะคืนค่าการอ้างอิงเดียวกันของหมากรุกเสมอ [หากใช้งานเป็นแบบคงที่] - วิธีจัดการสถานการณ์สมมติอย่างมีประสิทธิภาพที่สุด
Arnab Dutta

ฉันได้รับตัวอย่างของโรงงานที่ไม่คงที่ คุณสามารถใช้มันกับบล็อกแบบคงที่และวิธีการถ้าคุณต้องการ เกี่ยวกับคำค้นหาของคุณ: 1. ลูกค้าจะโทรไปที่ Factory เพื่อรับ Game 2. ฉันใส่วัตถุเพียงครั้งเดียวและทุกสิ่งจะได้รับจะคืนอินสแตนซ์เดียวกัน - referenc.e เดียวกันของหมากรุกจะถูกส่งคืนสำหรับทุก ๆ ครั้ง
Ravindra babu

6

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


4

คลาสโรงงานมีประโยชน์เมื่อประเภทวัตถุที่ส่งคืนมีคอนสตรัคเตอร์ส่วนตัวเมื่อคลาสโรงงานที่แตกต่างกันตั้งค่าคุณสมบัติต่าง ๆ บนวัตถุที่ส่งคืนหรือเมื่อประเภทโรงงานที่เฉพาะเจาะจงนั้นมาพร้อมกับประเภทคอนกรีตที่ส่งคืน

WCFใช้คลาส ServiceHostFactory เพื่อดึงออบเจ็กต์ ServiceHost ในสถานการณ์ที่แตกต่างกัน ServiceHostFactory มาตรฐานจะถูกใช้โดย IIS เพื่อดึงอินสแตนซ์ของServiceHostสำหรับไฟล์. svcแต่ใช้ WebScriptServiceHostFactory สำหรับบริการที่ส่งคืนซีเรียลเวอร์ไปยังไคลเอนต์ JavaScript ADO.NET Data Services มี DataServiceHostFactory พิเศษของตัวเองและ ASP.NET มี ApplicationServicesHostFactory เนื่องจากบริการของมันมีคอนสตรัคเตอร์ส่วนตัว

หากคุณมีคลาสหนึ่งคลาสที่ใช้งานโรงงานคุณสามารถใช้วิธีการของโรงงานภายในคลาสนั้นได้


2

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

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

1- คุณสร้าง Constructor Overload ซึ่งจะทำงานเฉพาะกับการใช้งานใหม่ (ไม่ยอมรับ). 2- คุณเปลี่ยนลายเซ็นคำสั่งซื้อ () และเปลี่ยนการขอร้องทุกครั้ง (ไม่ใช่การฝึกฝนที่ดีและความเจ็บปวดที่แท้จริง)

หากคุณสร้างโรงงานสำหรับระดับคำสั่งซื้อคุณจะต้องเปลี่ยนรหัสหนึ่งบรรทัดและคุณก็พร้อมที่จะไป ฉันแนะนำคลาสโรงงานสำหรับการรวมกลุ่มเกือบทุกครั้ง หวังว่าจะช่วย


1

หากคุณต้องการสร้างวัตถุที่แตกต่างในแง่ของการใช้งาน มันมีประโยชน์

public class factoryMethodPattern {
      static String planName = "COMMERCIALPLAN";
      static int units = 3;
      public static void main(String args[]) {
          GetPlanFactory planFactory = new GetPlanFactory();
          Plan p = planFactory.getPlan(planName);
          System.out.print("Bill amount for " + planName + " of  " + units
                        + " units is: ");
          p.getRate();
          p.calculateBill(units);
      }
}

abstract class Plan {
      protected double rate;

      abstract void getRate();

      public void calculateBill(int units) {
            System.out.println(units * rate);
      }
}

class DomesticPlan extends Plan {
      // @override
      public void getRate() {
            rate = 3.50;
      }
}

class CommercialPlan extends Plan {
      // @override
      public void getRate() {
            rate = 7.50;
      }
}

class InstitutionalPlan extends Plan {
      // @override
      public void getRate() {
            rate = 5.50;
      }
}

class GetPlanFactory {

      // use getPlan method to get object of type Plan
      public Plan getPlan(String planType) {
            if (planType == null) {
                  return null;
            }
            if (planType.equalsIgnoreCase("DOMESTICPLAN")) {
                  return new DomesticPlan();
            } else if (planType.equalsIgnoreCase("COMMERCIALPLAN")) {
                  return new CommercialPlan();
            } else if (planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {
                  return new InstitutionalPlan();
            }
            return null;
      }
}

1

คลาสใดก็ตามที่ชะลอการสร้างออบเจ็กต์ไปยังคลาสย่อยสำหรับออบเจ็กต์ที่ต้องการทำงานด้วยนั้นสามารถดูได้เป็นตัวอย่างของรูปแบบของ Factory

ฉันได้กล่าวถึงอย่างละเอียดในคำตอบอื่นที่https://stackoverflow.com/a/49110001/504133


1

ฉันคิดว่ามันจะขึ้นอยู่กับระดับการมีเพศสัมพันธ์ที่คุณต้องการนำมาใช้กับรหัสของคุณ

วิธีการโรงงาน decouples สิ่งที่ดีมาก แต่ไม่มีหมายเลขโรงงาน

กล่าวอีกนัยหนึ่งมันง่ายกว่าที่จะเปลี่ยนสิ่งต่าง ๆ ถ้าคุณใช้วิธีการจากโรงงานกว่าถ้าคุณใช้โรงงานแบบง่าย ๆ (เรียกว่าคลาสโรงงาน)

ดูเป็นตัวอย่างนี้https://connected2know.com/programming/java-factory-pattern/ ตอนนี้จินตนาการว่าคุณต้องการนำสัตว์ใหม่ ในคลาสโรงงานคุณต้องเปลี่ยนโรงงาน แต่ในวิธีการจากโรงงานไม่ใช่คุณเพียงแค่เพิ่มคลาสย่อยใหม่


0

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

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


0

ฉันเปรียบโรงงานตามแนวคิดของห้องสมุด ตัวอย่างเช่นคุณสามารถมีห้องสมุดสำหรับทำงานกับตัวเลขและอีกห้องสมุดสำหรับทำงานกับรูปร่าง คุณสามารถจัดเก็บฟังก์ชั่นของไลบรารีเหล่านี้ในไดเรกทอรีที่ตั้งชื่อตามหลักเหตุผลNumbersหรือShapesหรือเหล่านี้เป็นประเภททั่วไปที่อาจรวมถึงจำนวนเต็ม, ลอย, dobules, longs หรือ rectangles, วงกลม, สามเหลี่ยม, รูปห้าเหลี่ยมในกรณีของรูปร่าง

Petter จากโรงงานใช้ polymorphism, การฉีดพึ่งพาและ Inversion of control

วัตถุประสงค์ที่ระบุไว้ของรูปแบบโรงงานคือ: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

สมมุติว่าคุณกำลังสร้างระบบปฏิบัติการหรือกรอบงานและคุณกำลังสร้างส่วนประกอบที่ไม่ต่อเนื่องทั้งหมด

นี่คือตัวอย่างง่ายๆของแนวคิดของรูปแบบโรงงานใน PHP ฉันอาจจะไม่ได้ 100% จากทั้งหมด แต่ตั้งใจให้เป็นตัวอย่างง่ายๆ ฉันไม่ใช่ผู้เชี่ยวชาญ

class NumbersFactory {
    public static function makeNumber( $type, $number ) {
        $numObject = null;
        $number = null;

        switch( $type ) {
            case 'float':
                $numObject = new Float( $number );
                break;
            case 'integer':
                $numObject = new Integer( $number );
                break;
            case 'short':
                $numObject = new Short( $number );
                break;
            case 'double':
                $numObject = new Double( $number );
                break;
            case 'long':
                $numObject = new Long( $number );
                break;
            default:
                $numObject = new Integer( $number );
                break;
        }

        return $numObject;
    }
}

/* Numbers interface */
abstract class Number {
    protected $number;

    public function __construct( $number ) {
        $this->number = $number;
    }

    abstract public function add();
    abstract public function subtract();
    abstract public function multiply();
    abstract public function divide();
}
/* Float Implementation */
class Float extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Integer Implementation */
class Integer extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Short Implementation */
class Short extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Double Implementation */
class Double extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Long Implementation */
class Long extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}

$number = NumbersFactory::makeNumber( 'float', 12.5 );

ฉันเข้าใจสิ่งที่เกิดขึ้นที่นี่ แต่ฉันไม่เข้าใจว่ามันคืออะไร จะNumbersFactory::makeNumber( 'float', 12.5 );ให้อะไรฉันเพียงแค่บอกว่าnew Float(12.5);ถ้าฉันรู้ว่าฉันต้องการFloat? นี่คือสิ่งที่ฉันไม่เข้าใจเกี่ยวกับโรงงาน ... ประเด็นคืออะไร?
BadHorsie

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