2009-06-22 11 views
5

Tôi đã làm việc với mã java được cho là sử dụng mẫu Nhà máy, nhưng tôi không hoàn toàn bị thuyết phục bởi mẫu.Mẫu nhà máy trong java

Mã của tôi thực hiện điều này:

// the factory 
class SomeFactoryImpl { 
    Set<SomeClass> getSomeListOfObjects(); 
} 

Và ở đâu đó trong các mã:

{ ... 
    SomeFactory factory = new SomeFactoryImpl(); 
    Set<SomeClass> list = factory.getSomeListOfObjects(); 
} 

Điểm Tôi đang cân nhắc là, nếu lớp nhà máy không có một phương pháp tĩnh tạo() , sau đó, bạn cần phải khởi tạo một nhà máy, IMO sẽ phức tạp như việc tạo một đối tượng.

Tôi không xem xét lập luận rằng một nhà máy như vậy có thể trả về bộ sưu tập các đối tượng được tạo ra là đủ tốt. Tôi cảm thấy có thể có cách giải quyết rõ ràng hơn, nếu một trường hợp nhà máy cần phải được tạo ra trước khi thực sự tạo ra các đối tượng từ nhà máy.

Tôi cảm thấy tốt hơn nếu phương pháp tạo là phương pháp tĩnh của lớp nhà máy. Nhưng tôi cũng chắc chắn rằng ý kiến ​​của tôi không hoàn toàn "đúng".

Vì vậy, cộng đồng SO có thể đưa ra các ví dụ khi tạo đối tượng Factory ngay lập tức tốt hơn sử dụng các phương thức tạo tĩnh không?

Ngoài ra, tôi đã trả lời câu hỏi tương tự, liệt kê các liên kết này và câu trả lời: vì vậy tôi cần biết rõ sự khác biệt giữa FactoryMethodPattern, FactoryMethodCreationMethod với các ví dụ mã.

+0

Đó là khá phổ biến trong Java API như TRAX có một phương pháp newInstance tĩnh() trên lớp nhà máy (ví dụ TransformerFactory.newInstance()), và sau đó bạn gọi hàm createTransformer() trên kết quả. – skaffman

Trả lời

5

Sử dụng phiên bản của nhà máy cho thấy lợi ích thực sự khi kết hợp với tiêm phụ thuộc.

Vì vậy, trong ví dụ của bạn, thay vì:

{ ... 
    SomeFactory factory = new SomeFactoryImpl(); 
    Set<SomeClass> list = factory.getSomeListOfObjects(); 
} 

Bạn sẽ có:

public ThisClass(SomeFactory someFactory) { 
    this.factory = someFactory; 
} 

sau đó ...

{ ... 
    Set<SomeClass> list = factory.getSomeListOfObjects(); 
} 

Một số điểm:

  • Trong trường hợp này lớp học của bạn không có bất kỳ tham chiếu đến một nhà máy cụ thể, và không cần phải biết về SomeFactoryImpl, nó chỉ biết về SomeFactory trừu tượng.
  • Trong trường hợp này, trường hợp nhà máy đang được truyền xung quanh có thể được cấu hình trên cơ sở cá thể, chứ không phải là cơ sở tĩnh, có xu hướng (theo ý kiến ​​của tôi) là cách tốt hơn để xử lý nó. Nếu bạn có thể làm cho trường hợp nhà máy bất biến sau đó bạn thực sự có thể cắt giảm những lo lắng đa luồng. Có một cuộc gọi tĩnh để cung cấp cho bạn một ví dụ không thực sự tốt hơn, tham chiếu đến lớp tạo ra nó vẫn là chi tiết triển khai cụ thể, nó chỉ cao hơn - mặc dù điều đó có thể làm cho nó đủ cao để giải quyết vấn đề của bạn .

Tôi biết điều này chỉ đề cập đến một tập hợp con của câu hỏi của bạn ...

+1

+1 Ồ, vâng .. kết hợp điều này với một khung DI và thử nghiệm sẽ trở thành khá nhiều một Cakewalk. Cảm ơn! – jrharshath

1

Tôi đoán, một phương pháp tĩnh để tạo đối tượng là cách tiếp cận phổ biến nhất, nhưng cũng có một số trường hợp sử dụng khi tạo ví dụ ban đầu cho nhà máy. Ví dụ nếu bạn muốn kết hợp nó với một đăng ký (nơi nhiều đăng ký nên được phép cùng tồn tại).

Ngoài ra, nếu nhà máy dựa vào một số thông tin ngữ cảnh động (kết nối cơ sở dữ liệu, ...), theo ý kiến ​​của tôi thì tốt hơn là để cho nhà máy xử lý trường hợp này.

1

Trước hết bạn đang quên mục đích chính của các mô hình nhà máy, tôi mở cuốn sách của nhóm bốn và nó khẳng định:

"Xác định một giao diện cho việc tạo ra một Objet, nhưng hãy để lớp con quyết định lớp để nhanh chóng. Phương thức Factory cho phép một class trì hoãn instantiation cho các lớp con. "

Điều này có nghĩa là bạn thực sự xác định giao diện, do đó, SomeFactoryImpl thực sự nên triển khai giao diện được xác định ở một nơi khác. Điều này có ích khi bạn có nhiều đối tượng cần được khởi tạo nhưng bạn không muốn quan tâm đến loại đối tượng nào. Ví dụ: tôi đã sử dụng chúng để phát triển một ứng dụng xoay từ xa mà khách hàng tải xuống thông qua serialization định nghĩa của một số lớp không tồn tại trong máy khách. Mỗi lớp đã định nghĩa một lớp con của JPanel, cái nhìn cụ thể của nó nhưng khi tiếp cận với máy khách, tôi phải tìm cách để chứng minh các lớp này mà không biết chúng vì vậy tôi đã sử dụng một mẫu nhà máy để gọi lớp nhà máy và để nó khởi tạo đối tượng uknown của tôi. đang mở rộng một lớp con của JPanel do tôi xác định). Một ví dụ khác là tạo ra đối tượng cụ thể theo từng trường hợp cho phù hợp với nhu cầu của bạn. Ví dụ (như đã nêu trong trang wikipedia liên quan đến mẫu thiết kế này), bạn có thể nghĩ rằng một nhà máy xây dựng đối tượng và sau đó là một nhà máy khác cho cùng một loại đối tượng nhưng được sử dụng để tạo ra "đối tượng giả" sẽ thất bại một số loại thử nghiệm đơn vị.

Tuy nhiên bạn cũng có thể giải quyết vấn đề cụ thể của mình bằng các phương pháp tĩnh nhưng hãy nghĩ đến việc tách phần tạo ra các mục từ phần sử dụng chúng trong một dự án lớn. Tất nhiên ai đang phát triển phần khách hàng chỉ nên biết giao diện nhà máy nào được sử dụng và chỉ biết điều này để sử dụng tất cả các đối tượng definet ở phần khác.

Mẫu tạo là một loại mẫu 'cơ sở' được sử dụng chỉ để xác định phiên bản tùy chỉnh của nhà xây dựng mà không lo lắng sử dụng định nghĩa chuẩn (có tên của phương thức tương đương với tên của lớp). Chỉ là một cách khác nhau để thực hiện các đối tượng .. mẫu tạo ra thực sự không giải quyết bất kỳ loại vấn đề cụ thể nào (không bao gồm các hàm tạo với cùng một số và kiểu đối số).

+0

Tôi nghĩ rằng SomeFactoryImpl của anh ấy thực sự là một triển khai của một giao diện, mặc dù nó không được tuyên bố rõ ràng. (Thực ra, dòng SomeFactory factory = new SomeFactoryImpl(); là đủ rõ ràng). – glmxndr

0

Đây là lý do tôi tạo ra trường hợp của nhà máy đối tượng

  1. nó cho phép tôi để tạo ra một nhà máy, cấu hình nó (để tạo blue widgets vs widget đỏ vv) và sau đó có nó có sẵn để tạo ra blue widgets của tôi , tiện ích màu đỏ theo yêu cầu. Lưu ý rằng điều này khác với việc có một số RedWidgetFactory, BlueWidgetFactory. Cấu hình là trực giao với (các) loại đối tượng được tạo ra
  2. nó làm giảm các vấn đề luồng có thể xảy ra mà bạn có thể gặp phải một nhà máy (được truy cập qua phương pháp tĩnh) được sử dụng trong toàn bộ hệ thống của bạn. Điều này có lẽ là một chút phòng thủ, nhưng tôi đã tìm thấy đó là một tư duy tốt để có (đặc biệt là trong các hệ thống khá lớn). Tất nhiên nó phụ thuộc như thế nào đối tượng của bạn được tạo ra (ví dụ như không nhà máy của bạn tạo các thành phần cơ bản được chia sẻ)
+0

Tôi đồng ý với các vấn đề luồng và phần đồng thời, nhưng quyền hạn có mùi của tôi cho tôi biết rằng RedWidgetFactory là một ý tưởng tốt hơn so với factory.setProductColor ('đỏ'). Bạn có/Bạn không đồng ý? – jrharshath

+0

Có lẽ đó là một ví dụ tồi. Nhưng hãy tưởng tượng nếu bạn có 10.000 màu. Bạn sẽ không có một lớp nhà máy khác nhau cho mỗi người. Trong khi bạn có thể có một lớp và nhà máy khác nhau để tạo các bộ đối tượng rời rạc với các hành vi khác nhau. –

0

IMO, mã bạn có mẫu thực sự là một thích hợp của mô hình GOF Abstract Factory, ngay cả khi việc sử dụng nó không hoàn toàn tối ưu. Nếu tôi nhớ lại chính xác, cuốn sách GoF mô tả mối quan hệ giữa các nhà máy (SomeFactory, SomeFactoryImpl) và các sản phẩm (SomeClass) nhưng để lại các chi tiết cụ thể của các nhà máy instantiating mở.

Nếu những gì bạn có là API nội bộ sẽ không được sử dụng rộng rãi, những gì bạn có có thể là đủ. Nếu không, bạn có thể:

  1. Có một lớp khác (một "nhà quản lý nhà máy" nói) chọn triển khai nhà máy của bạn dựa trên thông số (ví dụ: DriverManager trong JDBC) hoặc thông tin ngữ cảnh khác.
  2. Sử dụng một số loại khung tiêm phụ thuộc.

Nếu đi với # 1, cá nhân tôi thường cố gắng và làm mẫu sau JDBC, trong đó:

  • Driver sẽ là nhà máy trừu tượng
  • Connections, Statements vv là những sản phẩm
  • DriverManager (không được chỉ định trong sách GoF rõ ràng) là lớp tiện ích chọn một nhà máy cho bạn dựa trên URL JDBC được truyền trong

(Trong trường hợp này, DriverManager sẽ tiếp tục và tạo ra sản phẩm cho bạn, nếu bạn sử dụng các phương pháp getConnection(...), như hầu hết.)

Để buộc nó trở lại câu hỏi của bạn, người ta cho là có thể sử dụng JDBC bằng cách gọi

new OracleDriver().connect(...) 

Nhưng khi ra nhọn của mình, đây là tiểu tối ưu, và phần nào đánh bại mục đích của việc sử dụng Abstract Factory .

Vấn đề này thường làm phiền tôi nhiều, cho đến khi tôi nhận ra một ngày rằng mô hình đó thực sự không nói rõ về cách các nhà máy được tạo ra.

Tôi hy vọng điều này sẽ trả lời câu hỏi của bạn.