Mẫu thiết kế: Phương pháp Factory vs Factory vs Tóm tắt Factory


183

Tôi đã đọc các mẫu thiết kế từ một trang web

Ở đó tôi đọc về Factory, phương thức Factory và Tóm tắt nhà máy nhưng chúng rất khó hiểu, không rõ ràng về định nghĩa. Theo định nghĩa

Factory - Tạo các đối tượng mà không để lộ logic khởi tạo cho máy khách và Tham chiếu đến đối tượng mới được tạo thông qua một giao diện chung. Là phiên bản đơn giản hóa của Phương thức xuất xưởng

Phương thức xuất xưởng - Xác định giao diện để tạo đối tượng, nhưng hãy để các lớp con quyết định lớp nào sẽ khởi tạo và Tham chiếu đến đối tượng mới được tạo thông qua giao diện chung.

Tóm tắt Factory - Cung cấp giao diện để tạo một họ các đối tượng liên quan, mà không chỉ định rõ ràng các lớp của chúng.

Tôi cũng đã xem các luồng stackoverflow khác liên quan đến Tóm tắt Factory vs Factory Phương thức nhưng các sơ đồ UML được vẽ ở đó làm cho sự hiểu biết của tôi thậm chí còn tồi tệ hơn.

Ai đó có thể vui lòng cho tôi biết

  1. Ba mẫu này khác nhau như thế nào?
  2. Khi nào nên sử dụng?
  3. Và nếu có thể, bất kỳ ví dụ java liên quan đến các mẫu này?

3
Trong khi tôi đang tìm kiếm câu trả lời cho câu hỏi gần giống như OP, tôi đã tìm thấy bài viết này: Từ Không có Nhà máy đến Phương pháp Nhà máy . Nó cung cấp cái nhìn sâu sắc bằng cách theo dõi sự phát triển của một dự án mẫu (phương pháp nhà máy được đề cập trong tiêu đề là một trong những bước tiến hóa).
Nick Alexeev

Câu trả lời:


250

Tất cả ba loại Factory đều làm điều tương tự: Chúng là một "nhà xây dựng thông minh".

Giả sử bạn muốn có thể tạo hai loại Trái cây: Táo và Cam.

Nhà máy

Nhà máy là "cố định", trong đó bạn chỉ có một triển khai không có phân lớp. Trong trường hợp này, bạn sẽ có một lớp như thế này:

class FruitFactory {

  public Apple makeApple() {
    // Code for creating an Apple here.
  }

  public Orange makeOrange() {
    // Code for creating an orange here.
  }

}

Trường hợp sử dụng: Xây dựng Apple hoặc Orange quá phức tạp để xử lý trong hàm tạo.

Phương pháp nhà máy

Phương pháp nhà máy thường được sử dụng khi bạn có một số cách chế biến chung trong một lớp, nhưng muốn thay đổi loại trái cây bạn thực sự sử dụng. Vì thế:

abstract class FruitPicker {

  protected abstract Fruit makeFruit();

  public void pickFruit() {
    private final Fruit f = makeFruit(); // The fruit we will work on..
    <bla bla bla>
  }
}

... Sau đó, bạn có thể sử dụng lại chức năng phổ biến FruitPicker.pickFruit()bằng cách triển khai phương thức xuất xưởng trong các lớp con:

class OrangePicker extends FruitPicker {

  @Override
  protected Fruit makeFruit() {
    return new Orange();
  }
}

Nhà máy trừu tượng

Nhà máy trừu tượng thường được sử dụng cho những thứ như tiêm / chiến lược phụ thuộc, khi bạn muốn có thể tạo ra cả một gia đình các đối tượng cần phải "cùng loại" và có một số lớp cơ sở chung. Đây là một ví dụ mơ hồ liên quan đến trái cây. Trường hợp sử dụng ở đây là chúng tôi muốn đảm bảo rằng chúng tôi không vô tình sử dụng OrangePicker trên Apple. Chừng nào chúng tôi nhận được Fruit and Picker từ cùng một nhà máy, chúng sẽ khớp với nhau.

interface PlantFactory {

  Plant makePlant();

  Picker makePicker(); 

}

public class AppleFactory implements PlantFactory {
  Plant makePlant() {
    return new Apple();
  }

  Picker makePicker() {
    return new ApplePicker();
  }
}

public class OrangeFactory implements PlantFactory {
  Plant makePlant() {
    return new Orange();
  }

  Picker makePicker() {
    return new OrangePicker();
  }
}

8
+1 Đây là câu trả lời giống với hiểu biết của tôi nhất về các mẫu này. Thêm ví dụ về mã gọi (Client) cũng sẽ giúp ích? Câu hỏi làm phiền tôi rất nhiều là: chúng ta có thể nói rằng Tóm tắt Mô hình Nhà máy chỉ là Nhà máy được mở rộng với Mô hình Phương thức Nhà máy (nếu điều này là đúng, tôi rõ ràng về chủ đề này)?
croraf

9
Đây là ví dụ tôi đã dành nhiều năm để tìm kiếm.
Taztingo

Đó là một lời giải thích tuyệt vời! Cảm ơn!
André Andrade

@ AndréAndrade Làm thế nào để gọi Phương thức xuất xưởng ? Một mã nhỏ xin vui lòng :) Điều đó sẽ xóa tan nghi ngờ của tôi về việc sử dụng nó
Arnab Dutta

25
  1. Ba mẫu này khác nhau như thế nào?

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

Phương thức Factory: 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

Nhà máy trừu tượng: Cung cấp giao diện để tạo các họ của các đối tượng liên quan hoặc phụ thuộc mà không chỉ định các lớp cụ thể của chúng.

Mẫu AbstractFactory sử dụng thành phần để ủy thác trách nhiệm tạo đối tượng cho lớp khác trong khi mẫu thiết kế phương thức Factory sử dụng tính kế thừa và dựa vào lớp dẫn xuất hoặc lớp con để tạo đối tượng

  1. Khi nào nên sử dụng?

Nhà máy: Khách hàng chỉ cần một lớp và không quan tâm đến việc triển khai cụ thể.

Phương thức xuất xưởng: Khách hàng khô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.

AbstactFactory: Khi hệ thống của bạn phải tạo nhiều họ sản phẩm hoặc bạn muốn cung cấp một thư viện sản phẩm mà không để lộ chi tiết triển khai.

Các lớp Factory trừu tượng thường được thực hiện với Phương thức Factory. Phương thức xuất xưởng thường được gọi trong Phương thức mẫu.

  1. Và nếu có thể, bất kỳ ví dụ java liên quan đến các mẫu này?

Nhà máy và Nhà máyMethod

Ý định:

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 một lớp trì hoãn khởi tạo đến các lớp con.

Sơ đồ UML :

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: Thực hiện 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ã:

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

So sánh với các mẫu sáng tạo khác:

  1. Thiết kế bắt đầu sử dụng Phương thức nhà máy (ít phức tạp hơn, tùy biến hơn, các lớp con tăng sinh) và phát triển theo hướng Tóm tắt Factory, Prototype hoặc Builder (linh hoạt hơn, phức tạp hơn) khi nhà thiết kế phát hiện ra nơi nào cần linh hoạt hơn

  2. Các lớp Factory trừu tượng thường được triển khai với Phương thức Factory , nhưng chúng cũng có thể được thực hiện bằng Prototype

Tài liệu tham khảo để đọc thêm: Mẫu thiết kế trang trí


Đối với Phương thức xuất xưởng, không nên xác định siêu lớp?
Tony Lin

20

Factory - Lớp Factory riêng biệt để tạo đối tượng phức tạp.

Ví dụ: Lớp FruitFactory để tạo đối tượng của Fruit

class FruitFactory{

public static Fruit getFruit(){...}

}

Phương thức nhà máy - Thay vì toàn bộ lớp riêng biệt cho nhà máy, chỉ cần thêm một phương thức trong chính lớp đó là nhà máy.

Ví dụ:

Calendar.getInstance() (Java's Calendar)

Tóm tắt phương pháp nhà máy - Nhà máy của nhà máy

Ví dụ: Hãy nói rằng chúng tôi muốn xây dựng nhà máy cho các bộ phận máy tính. Vì vậy, có một số loại máy tính như Laptop, Desktop, Server.

Vì vậy, đối với mỗi loại compter chúng ta cần nhà máy. Vì vậy, chúng tôi tạo ra một nhà máy highlevel của các nhà máy như dưới đây

ComputerTypeAbstractFactory.getComputerPartFactory(String computerType) ---> This will return PartFactory which can be one of these ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Bây giờ 3 chính nó là một lần nữa nhà máy. (Bạn sẽ tự xử lý PartFactory, nhưng trong phạm vi hoạt động, sẽ có triển khai riêng dựa trên những gì bạn cung cấp trong nhà máy trừu tượng)

  Interface-> PartFactory. getComputerPart(String s), 
Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Usage:
new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”)

EDIT: được chỉnh sửa để cung cấp giao diện chính xác cho Tóm tắt Factory theo sự phản đối trong các bình luận.


1
Ý tưởng đằng sau ComputerFactorysẽ là bạn có một giao diện tạo chung ( getScreen(); getKeyboard(); getDiskdrive(); ...) chứ không phải giao diện cho mỗi loại máy tính như bạn đề xuất. Bạn có thể ngửi thấy một vấn đề thiết kế nếu bạn sử dụng cùng một từ hai lần trong cùng một tuyên bố: Laptop Factory.get Phần máy tính xách tay ().
xtofl

Không không không, đừng đi chính xác vào mã. Nó chỉ là một anology cho sự hiểu biết. Nếu bạn muốn ví dụ chính xác với các giao diện, đây là. Đối tượng: Giao diện -> ComputerPart, Triển khai -> RAM, HDD, Bộ xử lý Nhà máy: Giao diện-> PartFactory. getComputerPart (Chuỗi s), Triển khai -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory. Abstract Factory: ComputerType.getPartFactory ( “String s”) Cách sử dụng:.. ComputerType mới () getFactory ( “máy tính xách tay”) getComputerPart ( “RAM”)
Ravi K

2
Tôi đã cập nhật câu trả lời để chăm sóc mối quan tâm của bạn. Trên thực tế nhà máy trừu tượng không có gì ngoài factoy của nhà máy mà thôi. Tôi đã đưa ra ví dụ trước đó chỉ để tham khảo (Giả sử người đọc sẽ quan tâm đến các giao diện trong khi thực hiện thực tế). Vẫn cảm ơn vì đã thông báo. Nó luôn luôn tốt để cải thiện. :)
Ravi K

Không abstract Factorykhông phải là một nhà máy của nhà máy ... Đó là abstract classhoặc interfacecó thể tạo ra một đối tượng sẽ được triển khai / mở rộng với các nhà máy bê tông khác nhau. Xem câu trả lời được chấp nhận để biết chi tiết mã. Và xin vui lòng loại bỏ hoặc chỉnh sửa câu trả lời của bạn cho phù hợp.
Julien__

Tôi thích cách giải thích về phương pháp nhà máy, đủ ngắn gọn để tiết lộ lý do tại sao nó được đặt tên như vậy. Trong mô hình này, nhà máy là phương thức, KHÔNG phải là lớp nói chung không phải là một tiện ích trợ giúp nhóm các phương thức khởi tạo mà chỉ có ý nghĩa. Câu trả lời công phu khác không may bỏ lỡ điểm này.
wlnirvana

11

Mỗi mẫu thiết kế phát triển mạnh để giúp đảm bảo rằng mã viết, làm việc không bị chạm. Tất cả chúng ta đều biết rằng một khi chúng ta chạm vào mã làm việc, có các lỗi trong các luồng làm việc hiện tại và cần phải thực hiện thêm nhiều thử nghiệm để đảm bảo rằng chúng ta không phá vỡ bất cứ điều gì.

Một mẫu nhà máy tạo các đối tượng dựa trên các tiêu chí đầu vào, do đó đảm bảo rằng bạn không cần phải viết mã như thế này nếu sau đó tạo đối tượng kinda này khác đối tượng kinda. Một ví dụ tốt về điều này là một trang web du lịch. Một trang web du lịch chỉ có thể cung cấp du lịch (chuyến bay, xe lửa, xe buýt) hoặc / và cung cấp khách sạn hoặc / và cung cấp các gói thu hút khách du lịch. Bây giờ, khi người dùng chọn tiếp theo, trang web cần quyết định những đối tượng nào cần tạo. Nên nó chỉ tạo đối tượng du lịch hoặc khách sạn quá.

Bây giờ, nếu bạn hình dung thêm một trang web khác vào danh mục đầu tư của mình và bạn tin rằng cùng một lõi được sử dụng, ví dụ, một trang web đi chung xe, hiện đang tìm kiếm taxi và thanh toán trực tuyến, bạn có thể sử dụng một nhà máy trừu tượng làm cốt lõi. Bằng cách này, bạn có thể chỉ cần chụp thêm một nhà máy taxi và xe chở khách.

Cả hai nhà máy không liên quan gì đến nhau, vì vậy đây là một thiết kế tốt để giữ chúng ở các nhà máy khác nhau.

Hy vọng điều này là rõ ràng bây giờ. Nghiên cứu trang web một lần nữa giữ ví dụ này trong tâm trí, hy vọng nó sẽ giúp. Và tôi thực sự hy vọng tôi đã đại diện cho các mẫu chính xác :).


3

Đối với câu trả lời này, tôi đề cập đến cuốn sách "Gang of Four".

Không có định nghĩa "Nhà máy" hay "Nhà máy đơn giản" hay "Nhà máy ảo" trong cuốn sách. Thông thường khi mọi người đang nói về mẫu "Factory", họ có thể đang nói về thứ gì đó tạo ra một đối tượng cụ thể của một lớp (nhưng không phải là mẫu "builder"); họ có thể hoặc không thể tham khảo các mẫu "Phương thức nhà máy" hoặc "Nhà máy trừu tượng". Bất cứ ai cũng có thể triển khai "Nhà máy" vì anh ấy sẽ không vì đó không phải là một thuật ngữ chính thức (hãy nhớ rằng một số người \ công ty \ cộng đồng có thể có vốn từ vựng của riêng họ).

Cuốn sách chỉ chứa các định nghĩa cho "Nhà máy trừu tượng" và "Phương pháp nhà máy".

Dưới đây là các định nghĩa từ cuốn sách và một lời giải thích ngắn về lý do tại sao cả hai có thể gây nhầm lẫn. Tôi bỏ qua các ví dụ mã bởi vì bạn có thể tìm thấy chúng trong các câu trả lời khác:

Phương thức xuất xưởng (GOF) : Xác định giao diện để tạo đối tượng, nhưng để 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.

Nhà máy trừu tượng (GOF) : Cung cấp giao diện để tạo các họ của các đối tượng liên quan hoặc phụ thuộc mà không chỉ định các lớp cụ thể của chúng.

Nguồn gốc của sự nhầm lẫn : Thông thường, người ta có thể gọi một lớp được sử dụng trong mẫu "Phương thức nhà máy" là "Nhà máy". Lớp này là trừu tượng theo định nghĩa. Đó là lý do tại sao dễ dàng gọi lớp này là "Nhà máy trừu tượng". Nhưng đó chỉ là tên của lớp học; bạn không nên nhầm lẫn nó với mẫu "Tóm tắt Factory" (tên lớp! = tên mẫu). Mẫu "Nhà máy trừu tượng" là khác nhau - nó không sử dụng một lớp trừu tượng; nó định nghĩa một giao diện (không nhất thiết là giao diện ngôn ngữ lập trình) để tạo các phần của một đối tượng lớn hơn hoặc các đối tượng có liên quan với nhau hoặc phải được tạo theo một cách cụ thể.


2
AbstractProductA, A1 and A2 both implementing the AbstractProductA
AbstractProductB, B1 and B2 both implementing the AbstractProductB

interface Factory {
    AbstractProductA getProductA(); //Factory Method - generate A1/A2
}

Sử dụng Phương thức xuất xưởng, người dùng có thể tạo A1 hoặc A2 của Tóm tắt sản phẩm.

interface AbstractFactory {
    AbstractProductA getProductA(); //Factory Method
    AbstractProductB getProductB(); //Factory Method
}

Nhưng Nhà máy Trừu tượng có nhiều hơn 1 phương thức xuất xưởng (ví dụ: 2 phương thức xuất xưởng), sử dụng các phương thức xuất xưởng đó, nó sẽ tạo ra tập hợp các đối tượng / đối tượng liên quan. Sử dụng Tóm tắt Factory, người dùng có thể tạo các đối tượng A1, B1 của Tóm tắt sản phẩm, Tóm tắt sản phẩm


0

Không ai đã trích dẫn cuốn sách gốc Các mẫu thiết kế: Các yếu tố của phần mềm hướng đối tượng có thể tái sử dụng , đưa ra câu trả lời trong hai đoạn đầu của phần Thảo luận về các mô hình sáng tạo (nhấn mạnh của tôi):

Có hai cách phổ biến để tham số hóa một hệ thống theo các lớp đối tượng mà nó tạo ra. Một cách là phân lớp lớp tạo các đối tượng; điều này tương ứng với việc sử dụng mẫu Phương thức nhà máy (107). Hạn chế chính của phương pháp này là nó có thể yêu cầu một lớp con mới chỉ để thay đổi lớp của sản phẩm. Những thay đổi như vậy có thể xếp tầng. Ví dụ: khi người tạo sản phẩm tự tạo bởi phương thức xuất xưởng, thì bạn cũng phải ghi đè trình tạo của sản phẩm.

Một cách khác để tham số hóa một hệ thống phụ thuộc nhiều hơn vào đối tượng thành phần : Xác định một đối tượng chịu trách nhiệm biết lớp của các đối tượng sản phẩm và biến nó thành một tham số của hệ thống. Đây là khía cạnh quan trọng của các mẫu Tóm tắt (87), Builder (97) và Prototype (117). Tất cả ba liên quan đến việc tạo ra một đối tượng nhà máy mới của Wikipedia, có trách nhiệm tạo ra các đối tượng sản phẩm. Tóm tắt Factory có đối tượng nhà máy sản xuất các đối tượng của một số lớp. Builder có đối tượng nhà máy xây dựng một sản phẩm phức tạp tăng dần bằng cách sử dụng một giao thức phức tạp tương ứng. Nguyên mẫu có đối tượng nhà máy xây dựng một sản phẩm bằng cách sao chép một đối tượng nguyên mẫu. Trong trường hợp này, đối tượng nhà máy và nguyên mẫu là cùng một đối tượng, bởi vì nguyên mẫu chịu trách nhiệm trả lại sản phẩm.

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.