2011-09-19 42 views
6

Theo cuốn sách:.nhà máy phương pháp thiết kế mẫu

Bản chất của mẫu máy này là "Xác định một giao diện cho tạo một đối tượng, nhưng để cho các lớp con quyết định lớp để nhanh chóng các phương pháp Factory cho phép một instantiation lớp hoãn đến lớp con

nói rằng tôi có một lớp Creator:.

class Product; //this is what the Factory Method should return 
class Creator { 
    public: 
     Creator() //ctor 
     { //... } 

     virtual Product make(//args) 
     { //... } 
} 

Ok, đó là lớp Đấng Tạo Hóa của tôi, nhưng tôi không hiểu

Phương pháp Factory cho phép một Hoãn instantiation lớp để lớp con

nó làm gì phải làm với các lớp con? Và tôi phải sử dụng các lớp con để làm gì?

Bất kỳ ai cũng có thể cho tôi một số ví dụ?

Trả lời

9

Lớp học Creator của bạn là nhà máy. Hãy gọi nó là ProductFactory, để làm cho ví dụ rõ ràng hơn.

(tôi đang giả sử bạn đang sử dụng C++)

class Book : public Product 
{ 
}; 

class Computer : public Product 
{ 
}; 

class ProductFactory 
{ 
public: 
    virtual Product* Make(int type) 
    { 
    switch (type) 
    { 
     case 0: 
     return new Book(); 
     case 1: 
     return new Computer(); 
     [...] 
    } 
    } 
} 

Gọi nó như thế này:

ProductFactory factory = ....; 
Product* p1 = factory.Make(0); // p1 is a Book* 
Product* p2 = factory.Make(1); // p2 is a Computer* 
// remember to delete p1 and p2 

Vì vậy, để trả lời câu hỏi của bạn:

gì nó phải làm gì với các lớp con? Và tôi phải sử dụng các lớp con nào cho các lớp học ?

Định nghĩa cho mẫu nhà máy là nhà sản xuất định nghĩa API chung để tạo các phiên bản của một loại nhất định (thường là giao diện hoặc lớp trừu tượng), nhưng loại thực thi được trả lại (do đó lớp con tham khảo) là trách nhiệm của nhà máy. Trong ví dụ này, nhà máy trả về Product trường hợp, trong đó BookComputer là các lớp con hợp lệ.

Có thành ngữ khác cho nhà máy, giống như có một API cho các nhà máy và việc triển khai cụ thể của nhà máy không chấp nhận một type như trong ví dụ của tôi, nhưng họ đang kết hợp với các loại hình trường trở về, như thế này :

class ProductFactory 
{ 
public: 
    virtual Product* Make() = 0; 
} 

class BookProductFactory : public ProductFactory 
{ 
public: 
    virtual Product* Make() 
    { 
     return new Book(); 
    } 
} 

Trong lớp này BookProductFactory luôn trả về Book trường hợp.

ProductFactory* factory = new BookProductFactory(); 
Product* p1 = factory->Make(); // p1 is a Book 
delete p1; 
delete factory; 

Để làm cho nó rõ ràng, vì dường như có một chút nhầm lẫn giữa Abstract FactoryFactory method các mẫu thiết kế, chúng ta hãy xem một ví dụ cụ thể:

Sử dụng Abstract Factory

class ProductFactory { 
protected: 
    virtual Product* MakeBook() = 0; 
    virtual Product* MakeComputer() = 0; 
} 

class Store { 
public: 
    Gift* MakeGift(ProductFactory* factory) { 
    Product* p1 = factory->MakeBook(); 
    Product* p2 = factory->MakeComputer(); 
    return new Gift(p1, p2); 
    } 
} 

class StoreProductFactory : public ProductFactory { 
protected: 
    virtual Product* MakeBook() { return new Book(); } 
    virtual Product* MakeComputer() { return new Computer(); } 
} 

class FreeBooksStoreProductFactory : public StoreProductFactory { 
protected: 
    virtual Product* MakeBook() { 
    Book* b = new FreeBook(); // a FreeBook is a Book with price 0 
    return b; 
    } 
} 

Được sử dụng như sau:

Store store; 
ProductFactory* factory = new FreeBooksStoreProductFactory(); 
Gift* gift = factory->MakeGift(factory); 
// gift has a FreeBook (Book with price 0) and a Computer 
delete gift; 
delete factory; 

Sử dụng phương pháp Factory

class Store { 
public: 
    Gift* MakeGift() { 
    Product* p1 = MakeBook(); 
    Product* p2 = MakeComputer(); 
    return new Gift(p1, p2); 
    } 

protected: 
    virtual Product* MakeBook() { 
    return new Book(); 
    } 

    virtual Product* MakeComputer() { 
    return new Computer(); 
    } 
} 

class FreeBooksStore : public Store { 
protected: 
    virtual Product* MakeBook() { 
    Book* b = new FreeBook(); // a FreeBook is a Book with price 0 
    return b; 
    } 
} 

Đó được sử dụng như thế này:

Store* store = new FreeBooksStore(); 
Gift* gift = store->MakeGift(); 
// gift has a FreeBook (Book with price 0) and a Computer 
delete gift; 
delete store; 

Khi bạn sử dụng một phân biệt type như tôi đã làm trong ví dụ ban đầu, chúng tôi đang sử dụng parametized factory methods - một phương pháp biết cách tạo các loại đối tượng khác nhau. Nhưng điều đó có thể xuất hiện ở dạng mẫu Abstract Factory hoặc Factory Method. Một mẹo ngắn gọn: nếu bạn đang mở rộng lớp nhà máy bạn đang sử dụng Abstract Factory. Nếu bạn mở rộng lớp bằng các phương thức tạo, thì bạn đang sử dụng các Phương thức của Nhà máy.

+0

vì vậy, trong mã của bạn, ProductFactory là một Nhà máy Tóm tắt, và thực hiện là Phương pháp Nhà máy, phải không? – Alcott

+0

Sự khác biệt giữa 'Abstract Factory' và' Factory Method' sẽ là câu hỏi riêng của nó :) Tóm lại, khi bạn sử dụng phân biệt kiểu như tôi đã làm trong ví dụ, chúng tôi đang sử dụng "phương pháp nhà máy được tối ưu hóa" - một phương pháp biết cách tạo các loại đối tượng khác nhau. Nhưng điều đó có thể xuất hiện trong mô hình Abstract Factory hoặc Factory Method. Một mẹo ngắn gọn: nếu bạn đang mở rộng lớp nhà máy bạn đang sử dụng 'Nhà máy trừu tượng'. Nếu bạn mở rộng lớp với phương thức _factory_, thì bạn đang sử dụng 'Method Methods'. Nếu sự khác biệt vẫn chưa rõ ràng đặt ra một câu hỏi khác trên SO. –

+0

Để làm rõ. Câu trả lời của tôi không sử dụng mẫu thiết kế 'Factory method' nhưng mẫu thiết kế' Abstract Factory'. –

3

Mẫu nhà máy chỉ đơn thuần có nghĩa là có một số loại Nhà máy hoặc phương pháp có trách nhiệm tạo đối tượng cho bạn; thay vì bạn tự tạo ra chúng. Giống như xe hơi được xây dựng trong các nhà máy, do đó bạn không cần phải.

Không có gì liên quan đến các lớp con, tuy nhiên tác giả có thể cố gắng nói rằng nhà máy thường có thể trả lại cho bạn việc thực hiện bắt nguồn từ lớp cơ sở dựa trên các tham số của bạn vì lớp con đó có thể làm những gì bạn yêu cầu trong tham số.

Ví dụ: WebRequest.Create ("http://www.example.com") sẽ trả lại cho tôi HttpWebRequest nhưng WebRequest.Create ("ftp://www.example.com") sẽ trả lại cho tôi FtpWebRequest vì cả hai đều có các giao thức khác nhau được triển khai bởi các lớp khác nhau nhưng giao diện công khai giống nhau nên quyết định này không phải do người tiêu dùng API của tôi thực hiện.

1

Sản phẩm Make() sẽ tạo đúng loại (phân lớp) của sản phẩm dựa trên các điều kiện nhất định và "trì hoãn" việc khởi tạo thực tế cho các sản phẩm cụ thể.

(psuedo đang)

public class Product 
{ 
    public static Product Make() 
    { 
     switch(day_of_week) 
     { 
      case Monday: return new Honey(1.1); 
      case Wednesday: return new Milk(3.6); 
      case Thurday: return new Meat(0.5); 
      case Friday: return new Vegetable(1.3); 
      case Saturday: return new Vegetable(2.3); // more expensive on saturday, only factory need to know 
      default: return null; // off day! 
     } 
    } 

    // returns price based on underlying product type and hidden/auto conditions (days of week) 
    public virtual void GetPrice() { return Price; } 

    // sometimes a factory can accept a product type enum 
    // From API POV, this is easier at a glance to know avaliable types. 
    pubic enum Type { Milk, Honey, Meat, Vegetable }; 

    public static Product Make(Type, Day) 
    { 
     // create the specified type for the specified day. 
    } 
} 

public class Honey : Product { Price = arg; } 
public class Milk : Product { Price = arg; } 
public class Meat : Product { Price = arg; } 
public class Vegetable : Product { Price = arg; } 

Factory ẩn các chi tiết có điều kiện cần thiết cho việc xây dựng các loại sản phẩm khác nhau. Thứ hai, IMHO, từ quan điểm người dùng API, thường dễ dàng hơn để xem loại sản phẩm nào (thường là từ một enum) và dễ dàng hơn để tạo chúng từ một điểm sáng tạo duy nhất.

+0

có nghĩa là, một phương pháp nhà máy có thể sản xuất (trả lại) một số sản phẩm, nhưng cái nào để tạo bên trong phương thức nhà máy và trả về được quyết định theo một số điều kiện (chẳng hạn như args được chuyển đến phương thức nhà máy). – Alcott

+0

@Alcott vui lòng xem thêm một số chi tiết được thêm vào câu trả lời của tôi. – Jake

0

Tôi chỉ có thể giả định ông có nghĩa này:

class Product; //this is what the Factory Method should return 
class Box : Product; 

class Creator { 
    public: 
     Creator() //ctor 
     { //... } 

     virtual Product* make(//args) = 0; 
}; 

class BoxCreator{ 
    public: 
     BoxCreator() 
     {} 
     virtual Product* make() 
     {} 
}; 

Creator* pCreator = new BoxCreator; 
Product* pProduct = pCreator->make(); //will create a new box 

Tuy nhiên đây không phải là một cách tiêu chuẩn để tạo ra một nhà máy.

+0

thì cách std là gì? – Alcott

+0

có tên phương thức khác nhau tùy thuộc vào loại trả lại hoặc như Jake đã chỉ ra, chỉ định loại đối tượng. –

0

Cung cấp các ví dụ như vậy trong mã giả là một chút khó hiểu, mẫu này phụ thuộc rất nhiều vào ngôn ngữ. Ví dụ của bạn trông giống như trong C++, nhưng nó không hợp lệ trong C++ vì make trả về Product theo giá trị.Điều này là hoàn toàn chống lại mục tiêu chính của Factory - để trả về một tham chiếu (con trỏ trong trường hợp C++) đến lớp cơ sở. Một số câu trả lời lấy điều này là C# hoặc Java (tôi đoán) khi những người khác là C++.

Factory mô hình dựa trên đa hình. Điểm mấu chốt là trả về một tham chiếu đến lớp cơ sở Product. Trẻ em của Factory sẽ tạo ra các thể hiện của các lớp cụ thể.

0

Tôi có cùng một sự nhầm lẫn "cho phép các lớp con quyết định lớp nào sẽ khởi tạo" -Bởi vì trong phương thức nhà máy triển khai sử dụng mới để tạo đối tượng "- tôi tham khảo Đầu mẫu thiết kế đầu tiên trong đó ghi rõ nó như sau: "Như trong định nghĩa chính thức, bạn sẽ nghe thường xuyên các nhà phát triển nói rằng để cho các lớp con quyết định lớp nào để khởi tạo. Họ nói" quyết định "không phải vì mẫu cho phép lớp con tự quyết định thời gian chạy, nhưng vì lớp người tạo được viết bằng kiến ​​thức của sản phẩm thực tế sẽ được tạo, được quyết định hoàn toàn bởi sự lựa chọn của lớp con được sử dụng "

0

Đơn giản và ngắn gọn:

Trong nhà máy, nó được kiểm tra mà "lớp con" được yêu cầu phải nhanh chóng để "let the subclasses decide which class to instantiate"
(Bạn sử dụng câu điều kiện trong lớp nhà máy nơi quyết định đã được thực hiện.)

"define an interface or abstract class for creating an object". rõ ràng, bạn lưu trữ đối tượng vào tham chiếu của giao diện và máy khách không biết đối tượng của lớp bê tông nào được trả về. (Vì vậy, bạn đã xác định một giao diện để tạo một đối tượng).

Các vấn đề liên quan