Mô hình nhà máy. Khi nào nên sử dụng phương pháp nhà máy?


Câu trả lời:


387

Tôi thích suy nghĩ về các thiết kế vỗ về các lớp của tôi là "con người", và các mẫu là cách mọi người nói chuyện với nhau.

Vì vậy, với tôi mô hình nhà máy giống như một công ty tuyển dụng. Bạn đã có ai đó sẽ cần một số lượng công nhân khác nhau. Người này có thể biết một số thông tin họ cần ở những người họ thuê, nhưng đó là thông tin đó.

Vì vậy, khi họ cần một nhân viên mới, họ gọi cho cơ quan tuyển dụng và nói với họ những gì họ cần. Bây giờ, để thực sự thuê một ai đó, bạn cần biết rất nhiều thứ - lợi ích, xác minh đủ điều kiện, v.v. Nhưng người tuyển dụng không cần biết gì về điều này - cơ quan tuyển dụng xử lý tất cả những điều đó.

Theo cách tương tự, sử dụng Factory cho phép người tiêu dùng tạo các đối tượng mới mà không cần phải biết chi tiết về cách họ tạo ra hoặc phụ thuộc của họ là gì - họ chỉ phải cung cấp thông tin họ thực sự muốn.

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

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

Vì vậy, bây giờ người tiêu dùng của ThingFactory có thể nhận được một Điều, mà không cần phải biết về sự phụ thuộc của Điều đó, ngoại trừ dữ liệu chuỗi đến từ người tiêu dùng.


17
Trường hợp triển khai cụ thể của GetThing () lấy các giá trị của FirstDependency và secondDependency?
Mikeyg36

88
Ai đó có thể cho tôi biết làm thế nào điều này trả lời câu hỏi của OP? Điều này chỉ mô tả 'Mô hình nhà máy' là gì và sau đó thêm một ví dụ về 'Phương thức nhà máy', đây chỉ là một trong ba 'Mô hình nhà máy'. Nói cách khác, tôi thấy không có so sánh ở bất cứ đâu.
Forethinker

4
Câu hỏi của OP đề cập rõ ràng within an object instead of a Factory class. Tôi nghĩ rằng anh ta có nghĩa là kịch bản nơi bạn đặt ctor riêng tư và sử dụng một phương thức tĩnh để khởi tạo lớp (tạo một đối tượng). Nhưng để làm theo ví dụ này, người ta phải khởi tạo ThingFactorylớp trước để lấy Thingcác đối tượng, điều này làm cho điều này Factory classcó hiệu lực.
atiyar

4
Xin lỗi, nhưng lời giải thích là tào lao, bởi vì một nhà xây dựng cũng có thể được viết theo cách để che giấu các phụ thuộc. Thông tin cơ bản chính mà bạn muốn tách thông tin tạo phụ thuộc khỏi quản lý phụ thuộc bị thiếu. Bên cạnh đó, câu hỏi là về cùng một lớp, câu trả lời là không có cách nào liên quan đến điều đó.
Christian Hujer

8
OP hỏi khi nào . Kyoryu trả lời thế nào . Mặc dù phong cách của câu trả lời là đáng khen ngợi, trong bối cảnh của câu hỏi này, nó chỉ là tiếng ồn.
8bitjunkie

96

Các phương thức của nhà máy nên được coi là một giải pháp thay thế cho các nhà xây dựng - chủ yếu là khi các nhà xây dựng không đủ biểu cảm, tức là.

class Foo{
  public Foo(bool withBar);
}

không biểu cảm như:

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

Các lớp Factory rất hữu ích khi bạn cần một quy trình phức tạp để xây dựng đối tượng, khi xây dựng cần một phụ thuộc mà bạn không muốn cho lớp thực tế, khi bạn cần xây dựng các đối tượng khác nhau, v.v.


2
Lớp Factory ở đâu?
Koray Tugay

20
@KorayTugay: Không có lớp nhà máy, chỉ có phương thức nhà máy. Câu hỏi là khi nào nên sử dụng phương thức nhà máy thay vì lớp nhà máy. Nhưng các phương thức của nhà máy là một sự thay thế cho các nhà xây dựng hơn là một sự thay thế cho các lớp học của nhà máy. (Tôi không biết tại sao câu trả lời hàng đầu được đánh giá cao như vậy mặc dù chỉ nói về các lớp học của nhà máy).
Rasmus Faber

5
Cần lưu ý rằng các phương thức nhà máy tĩnh hoàn toàn khác với mẫu thiết kế Gang of Four: Factory Method.
jaco0646

76

Một tình huống mà cá nhân tôi tìm thấy các lớp Factory riêng biệt có ý nghĩa là khi đối tượng cuối cùng bạn đang cố gắng tạo ra dựa vào một số đối tượng khác. Ví dụ, trong PHP: Giả sử bạn có một Houseđối tượng, lần lượt có một Kitchenvà một LivingRoomđối tượng và LivingRoomđối tượng cũng có một TVđối tượng bên trong.

Phương pháp đơn giản nhất để đạt được điều này là yêu cầu mỗi đối tượng tạo con cái trên phương thức xây dựng của chúng, nhưng nếu các thuộc tính được lồng tương đối, khi bạn Housekhông tạo được, bạn có thể sẽ mất một thời gian để cố gắng cách ly chính xác những gì đang thất bại.

Cách khác là làm như sau (tiêm phụ thuộc, nếu bạn thích thuật ngữ ưa thích):

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

Ở đây, nếu quá trình tạo ra một Housethất bại chỉ có một nơi để tìm, nhưng việc phải sử dụng đoạn này mỗi khi người ta muốn một cái mới Housethì không thuận tiện. Nhập các nhà máy:

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();

Nhờ vào nhà máy ở đây, quá trình tạo ra một Housebản tóm tắt (trong đó bạn không cần phải tạo và thiết lập mọi phụ thuộc duy nhất khi bạn chỉ muốn tạo một House) và đồng thời tập trung hóa để giúp duy trì dễ dàng hơn. Có nhiều lý do khác tại sao sử dụng các Nhà máy riêng biệt có thể có lợi (ví dụ: khả năng kiểm tra) nhưng tôi thấy trường hợp sử dụng cụ thể này để minh họa rõ nhất cách các lớp Factory có thể hữu ích.


1
Làm thế nào một người nào đó sẽ làm một bài kiểm tra đơn vị về điều này mặc dù? Tôi nghĩ rằng việc sử dụng từ khóa "mới" trong một lớp được coi là thực hành tồi vì nó không thể được kiểm tra đơn vị. Hay là một nhà máy có nghĩa là một chút ngoại lệ cho quy tắc đó?
AgmLauncher

1
@AgmLauncher Tôi cũng có câu hỏi tương tự khi bắt đầu thử nghiệm đơn vị, hãy xem: stackoverflow.com/questions/10128780/
Lỗi

1
Không có được điều này. Làm thế nào chính xác các thông số để tạo các đối tượng khác nhau được truyền cho HouseFactorylớp?
atiyar

1
@Mahn, cuối cùng bạn sẽ không có nhiều thông số không?
Pacerier

1
@Pacerier đó là thứ để bạn quyết định cách tạo mô hình, tùy thuộc vào nhu cầu của bạn, nhưng bạn không phải luôn truyền mọi tham số cho createphương thức. Ví dụ, nếu bạn Housesẽ luôn có cùng một loại LivingRoomthì có thể có các thông số được mã hóa cứng trong lớp nhà máy thay vì được truyền dưới dạng đối số. Hoặc bạn có thể muốn cung cấp một typeđối số cho HouseFactory::createphương thức của mình nếu bạn có một vài loại LivingRooms và có một công tắc bên trong với các tham số được mã hóa cứng cho từng loại.
Mahn

19

Điều quan trọng là phải phân biệt rõ ràng ý tưởng đằng sau việc sử dụng phương pháp nhà máy hoặc nhà máy. Cả hai đều nhằm giải quyết các loại vấn đề tạo đối tượng loại trừ lẫn nhau.

Hãy nói cụ thể về "phương pháp nhà máy":

Điều đầu tiên là, khi bạn đang phát triển thư viện hoặc API, lần lượt sẽ được sử dụng để phát triển ứng dụng, thì phương thức xuất xưởng là một trong những lựa chọn tốt nhất cho mẫu tạo. Lý do đằng sau; Chúng tôi biết rằng khi nào nên tạo một đối tượng có chức năng cần thiết nhưng loại đối tượng sẽ vẫn chưa được quyết định hoặc nó sẽ được quyết định tham số động ob được thông qua .

Bây giờ vấn đề là, gần như có thể đạt được bằng cách sử dụng chính mô hình nhà máy nhưng một nhược điểm lớn sẽ đưa vào hệ thống nếu mô hình nhà máy sẽ được sử dụng cho vấn đề được tô sáng ở trên, đó là logic của bạn đối với các đối tượng khác nhau (đối tượng lớp phụ) sẽ cụ thể với một số điều kiện kinh doanh vì vậy trong tương lai khi bạn cần mở rộng chức năng thư viện của mình cho các nền tảng khác (Về mặt kỹ thuật hơn, bạn cần thêm nhiều lớp phụ của giao diện cơ bản hoặc lớp trừu tượng để nhà máy cũng trả lại các đối tượng đó ngoài các đối tượng hiện có dựa trên một số tham số động) sau đó mỗi khi bạn cần thay đổi (mở rộng) logic của lớp nhà máy sẽ hoạt động tốn kém và không tốt từ quan điểm thiết kế. Mặt khác, nếu "phương pháp nhà máy"

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

Chúng cũng hữu ích khi bạn cần một số "hàm tạo" có cùng loại tham số nhưng với hành vi khác nhau.


15

Đó là ý tưởng tốt để sử dụng các phương thức nhà máy bên trong đối tượng khi:

  1. Lớp đối tượng không biết lớp con chính xác mà nó phải tạo
  2. Lớp đối tượng được thiết kế sao cho các đối tượng mà nó tạo ra được chỉ định bởi các lớp con
  3. Lớp đối tượng ủy thác nhiệm vụ của mình cho các lớp phụ trợ và không biết lớp chính xác nào sẽ nhận các nhiệm vụ này

Đó là ý tưởng tốt để sử dụng lớp nhà máy trừu tượng khi:

  1. Đối tượng của bạn không nên phụ thuộc vào cách các đối tượng bên trong của nó được tạo và thiết kế
  2. Nhóm các đối tượng được liên kết nên được sử dụng cùng nhau và bạn cần phục vụ ràng buộc này
  3. Đối tượng nên được cấu hình bởi một trong một số họ có thể của các đối tượng được liên kết sẽ là một phần của đối tượng cha của bạn
  4. Cần chia sẻ các đối tượng con chỉ hiển thị giao diện chứ không phải triển khai

9

UML từ

nhập mô tả hình ảnh ở đây

Sản phẩm: Nó định nghĩa một giao diện của các đối tượng mà phương thức Factory tạo ra.

ConcreteSản phẩm : Triển khai Giao diện sản phẩm

Người tạo: Khai báo phương thức Factory

ConcreateCreator: Triển khai phương thức Factory để trả về một thể hiện của Concrete sản phẩm

Báo cáo sự cố: Tạo Factory of Games bằng cách sử dụng Factory Methods, định nghĩa giao diện trò chơi.

Đoạn mã:

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");
        }           
    }
}

đầu ra:

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

Ví dụ này cho thấy một Factorylớp bằng cách thực hiện a FactoryMethod.

  1. Gamelà giao diện cho tất cả các loại trò chơi. Nó định nghĩa phương thức phức tạp:createGame()

  2. Chess, Ludo, Checkers là các biến thể khác nhau của trò chơi, cung cấp việc thực hiện cho createGame()

  3. public Game getGame(String gameName)đang FactoryMethodở trong IGameFactorylớp

  4. GameFactorytạo trước các loại trò chơi khác nhau trong hàm tạo. Nó thực hiện IGameFactoryphương pháp nhà máy.

  5. Tên trò chơi được truyền dưới dạng đối số dòng lệnh để NotStaticFactoryDemo

  6. getGametrong việc GameFactorychấp nhận một tên trò chơi và trả về Gameđối tượng tương ứng .

Nhà máy:

Tạo các đối tượng mà không để lộ logic khởi tạo cho máy khách.

Nhà máy

Xác định một giao diện để tạo một đối tượng, nhưng hãy để các lớp con quyết định lớp nào sẽ khởi tạo. Phương thức Factory cho phép khởi tạo lớp trì hoãn cho các lớp con

Trường hợp sử dụng:

Khi nào nên sử dụng: Clientkhông biết những lớp cụ thể nào sẽ được yêu cầu tạo trong thời gian chạy, nhưng chỉ muốn có một lớp sẽ thực hiện công việc.


cảm ơn bạn vì phần ghi chú của bạn, nó ngắn gọn cho tôi giao diện để tạo một đối tượng, nhưng hãy để các lớp con quyết định lớp nào sẽ khởi tạo "làm ơn.
reco

getArea()không phải là một phương pháp nhà máy ở tất cả .
Cranio

1
Tôi có một ý kiến ​​khác - các chuyên gia vui lòng xác nhận và ghi chú. 1. Khách hàng (hoặc Invoker) cần Object yêu thích ... vì thế không cần phải gọi GameFactory mới () thay vì lớp Factory nên có một getInstance tĩnh () 2.Ngoài Nếu vậy thì games.put (Chess.class.getName ( ), Cờ mới ()); sẽ luôn trả về cùng một tham chiếu của Tướng [nếu được triển khai dưới dạng tĩnh] - cách xử lý tình huống đó hiệu quả nhất?
Arnab Dutta

Tôi đã đưa ra ví dụ về Nhà máy không tĩnh. Bạn có thể thực hiện nó với các khối và phương thức tĩnh nếu bạn muốn. Về truy vấn của bạn: 1. Khách hàng sẽ gọi cho Factory để nhận Game. 2. Tôi đang đặt đối tượng một lần và tất cả Get sẽ trả về cùng một ví dụ - cùng một lượt giới thiệu về Cờ vua được trả lại cho mỗi lần nhận
Ravindra babu

6

Đó thực sự là một vấn đề của hương vị. Các lớp của nhà máy có thể được trừu tượng hóa / giao thoa khi cần thiết, trong khi các phương thức của nhà máy có trọng lượng nhẹ hơn (và cũng có xu hướng có thể kiểm tra được, vì chúng không có loại xác định, nhưng chúng sẽ yêu cầu một điểm đăng ký nổi tiếng, gần giống với dịch vụ định vị nhưng để định vị phương pháp nhà máy).


4

Các lớp nhà máy rất hữu ích khi loại đối tượng mà chúng trả về có một hàm tạo riêng, khi các lớp nhà máy khác nhau đặt các thuộc tính khác nhau trên đối tượng trả về hoặc khi một loại nhà máy cụ thể được ghép với loại bê tông trả về của nó.

WCF sử dụng các lớp ServicehostFactory để truy xuất các đối tượng Servicehost trong các tình huống khác nhau. ServicehostFactory tiêu chuẩn được IIS sử dụng để truy xuất các phiên bản Servicehost cho các tệp .svc, nhưng WebScriptServicehostFactory được sử dụng cho các dịch vụ trả về tuần tự hóa cho các máy khách JavaScript. Dịch vụ dữ liệu ADO.NET có DataServicehostFactory đặc biệt của riêng mình và ASP.NET có ApplicationServicehostFactory vì các dịch vụ của nó có các nhà xây dựng riêng.

Nếu bạn chỉ có một lớp tiêu thụ nhà máy, thì bạn chỉ có thể sử dụng một phương thức nhà máy trong lớp đó.


2

Hãy xem xét một kịch bản khi bạn phải thiết kế một lớp Đơn hàng và Khách hàng. Để đơn giản và các yêu cầu ban đầu, bạn không cảm thấy cần nhà máy cho lớp Đơn hàng và điền vào ứng dụng của bạn bằng nhiều câu lệnh 'Đơn hàng mới ()'. Mọi thứ đang hoạt động tốt.

Bây giờ một yêu cầu mới xuất hiện rằng đối tượng Đặt hàng không thể được khởi tạo mà không có liên kết Khách hàng (phụ thuộc mới). Bây giờ bạn có những cân nhắc sau đây.

1- Bạn tạo quá tải hàm tạo sẽ chỉ hoạt động cho các triển khai mới. (Không thể chấp nhận). 2- Bạn thay đổi chữ ký Order () và thay đổi mỗi lần gọi. (Không phải là một thực hành tốt và đau thực sự).

Thay vào đó Nếu bạn đã tạo một nhà máy cho Lớp Đặt hàng, bạn chỉ phải thay đổi một dòng mã và bạn sẽ ổn. Tôi đề nghị lớp Factory cho hầu hết các hiệp hội tổng hợp. Mong rằng sẽ giúp.


1

nếu bạn muốn tạo một đối tượng khác về mặt sử dụng. Nó rất hữu ích.

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

Bất kỳ lớp nào trì hoãn việc tạo đối tượng cho lớp con của nó cho đối tượng mà nó cần làm việc có thể được xem như một ví dụ về mẫu Factory.

Tôi đã đề cập chi tiết trong một câu trả lời khác tại https://stackoverflow.com/a/49110001/504133


1

Tôi nghĩ rằng nó sẽ phụ thuộc vào mức độ khớp nối lỏng lẻo mà bạn muốn mang đến mã của mình.

Phương pháp nhà máy tách rời mọi thứ rất tốt nhưng lớp nhà máy không có.

Nói cách khác, việc thay đổi mọi thứ sẽ dễ dàng hơn nếu bạn sử dụng phương thức nhà máy hơn là khi bạn sử dụng một nhà máy đơn giản (được gọi là lớp nhà máy).

Nhìn vào ví dụ này: https://connected2ledge.com/programming/java-factory-potype/ . Bây giờ, hãy tưởng tượng rằng bạn muốn mang một Động vật mới. Trong lớp Factory, bạn cần thay đổi Factory nhưng trong phương thức Factory, không, bạn chỉ cần thêm một lớp con mới.


0

Các lớp học nhà máy nặng hơn, nhưng cung cấp cho bạn một số lợi thế nhất định. Trong trường hợp khi bạn cần xây dựng các đối tượng của mình từ nhiều nguồn dữ liệu thô, chúng cho phép bạn chỉ gói gọn logic xây dựng (và có thể tổng hợp dữ liệu) ở một nơi. Ở đó nó có thể được kiểm tra một cách trừu tượng mà không cần quan tâm đến giao diện đối tượng.

Tôi đã tìm thấy đây là một mẫu hữu ích, đặc biệt khi tôi không thể thay thế và không đủ ORM và muốn khởi tạo hiệu quả nhiều đối tượng từ bảng DB tham gia hoặc các thủ tục được lưu trữ.


0

Tôi thích các nhà máy với khái niệm về thư viện. Ví dụ, bạn có thể có một thư viện để làm việc với các số và một thư viện khác để làm việc với các hình dạng. Bạn có thể lưu trữ các chức năng của các thư viện này trong các thư mục có tên logic là Numbershoặc Shapes. Đây là các loại chung có thể bao gồm số nguyên, phao, dobules, dài hoặc hình chữ nhật, hình tròn, hình tam giác, hình ngũ giác trong trường hợp hình dạng.

Petter nhà máy sử dụng đa hình, tiêm phụ thuộc và đảo ngược kiểm soát.

Mục đích đã nêu của các mẫu nhà máy là: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Vì vậy, giả sử rằng bạn đang xây dựng một Hệ điều hành hoặc Khung và bạn đang xây dựng tất cả các thành phần riêng biệt.

Dưới đây là một ví dụ đơn giản về khái niệm Mô hình nhà máy trong PHP. Tôi có thể không 100% cho tất cả nhưng nó dự định là một ví dụ đơn giản. Tôi không phải là một chuyên gia.

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 );

Tôi hiểu những gì đang xảy ra ở đây, nhưng tôi không hiểu ý nghĩa của nó là gì. Điều gì đang NumbersFactory::makeNumber( 'float', 12.5 );cho tôi hơn chỉ nói new Float(12.5);nếu tôi biết tôi cần một Float? Đây là những gì tôi không hiểu về các nhà máy ... vấn đề là gì?
BadHorsie

Nó cho phép bạn chọn các triển khai khác nhau và không ràng buộc bạn với chỉ một. Một giao diện được thiết lập và tất cả các triển khai phải đảm bảo và tôn vinh nó.
Robert Rocha
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.