Mục đích của mô hình nhà máy là để de-couple một số mã từ kiểu thời gian chạy của một đối tượng nó tiêu thụ:
// This code doesn't need to know that the factory is returning
// an object of type `com.example.parties.SurpriseParty`
AbstractParty myParty = new PartyFactory().create(...);
Sử dụng mã như thế này, PartyFactory
độc quyền chịu trách nhiệm xác định hoặc biết chính xác loại thời gian chạy nào nên được sử dụng.
Bạn đang bỏ qua lợi ích đó bằng cách chuyển tên đầy đủ của lớp bạn cần. Làm thế nào là thế này ...
// This code obviously DOES know that the factory is returning
// an object of type `com.example.parties.SurpriseParty`.
// Now only the compiler doesn't know or enforce that relationship.
AbstractParty myParty = new PartyFactory().create("com.example.parties.SurpriseParty");
... bất kỳ khác nhau từ đơn giản tuyên bố myParty
như là kiểu com.example.parties.SurpriseParty
? Cuối cùng, mã của bạn cũng giống như kết hợp, nhưng bạn đã từ bỏ xác minh loại tĩnh. Điều đó có nghĩa là bạn đang phát sinh ít hơn không có lợi ích trong khi đầu hàng một số lợi ích của Java được đánh máy mạnh mẽ. Nếu bạn xóa com.example.parties.SurpriseParty
mã của bạn sẽ vẫn biên dịch, IDE của bạn sẽ không cung cấp cho bạn thông báo lỗi và bạn sẽ không nhận ra có mối quan hệ giữa mã này và com.example.parties.SurpriseParty
cho đến khi thời gian chạy - điều đó không tốt.
Ít nhất, tôi muốn khuyên bạn nên ít nhất là thay đổi mã này để lập luận của phương pháp là một tên lớp đơn giản, không phải là một tên đầy đủ:
// I took the liberty of renaming this class and it's only method
public class MyPartyFactory{
public Party create(String name)
{
//TODO: sanitize `name` - check it contains no `.` characters
Class c = Class.forName("com.example.parties."+name);
// I'm going to take for granted that I don't have to explain how or why `party` shouldn't be an instance variable.
Party party = (PersonalParty)c.newInstance();
return party;
}
}
Tiếp theo: là nó xấu thực hành để sử dụng Class.forName(...)
? Điều đó phụ thuộc vào lựa chọn thay thế là gì và mối quan hệ giữa các đối số String
(name
) và các lớp mà nhà máy này sẽ cung cấp. Nếu phương án thay thế có điều kiện lớn:
if("SurpriseParty".equals(name) {
return new com.example.parties.SurpriseParty();
}
else if("GoodbyeParty".equals(name)) {
return new com.example.parties.GoodbyeParty();
}
else if("PartyOfFive".equals(name)) {
return new com.example.parties.PartyOfFive();
}
else if(/* ... */) {
// ...
}
// etc, etc etc
... không thể mở rộng được. Vì có mối quan hệ rõ ràng quan sát giữa tên của các kiểu thời gian chạy mà nhà máy này tạo ra và giá trị của đối số name
, bạn nên cân nhắc sử dụng Class.forName
thay thế. Bằng cách đó, đối tượng Factory
của bạn được bảo vệ khỏi việc cần thay đổi mã mỗi lần bạn thêm một loại Party
mới vào hệ thống.
Một số thứ khác bạn có thể xem xét là sử dụng mẫu AbstractFactory
thay thế. Nếu mã tốn của bạn trông như thế này:
AbstractParty sParty = new PartyFactory().create("SurpriseParty");
AbstractParty gbParty = new PartyFactory().create("GoodByeParty");
... nơi có một số hạn chế về thường xảy ra các loại bên được yêu cầu, bạn nên xem xét việc có phương pháp khác nhau đối với những loại khác nhau của các bên:
public class PartyFactory {
public Party getSurpriseParty() { ... }
public Party getGoodByeParty() { ... }
}
...điều này sẽ cho phép bạn tận dụng tính năng gõ tĩnh của Java. Tuy nhiên, giải pháp này có nghĩa là mỗi khi bạn thêm một loại mới Party
bạn phải thay đổi đối tượng nhà máy - vì vậy liệu giải pháp phản chiếu hay AbstractFactory
là giải pháp tốt hơn thực sự phụ thuộc vào tần suất và tốc độ của bạn sẽ thêm Party
loại. Một loại mới mỗi ngày? Sử dụng sự phản chiếu. Một loại đảng mới mỗi thập kỷ? Sử dụng một số AbstractFactory
.
Có bất kỳ ứng dụng nghiêm túc nào cho việc này không. Nói chung, tôi sẽ xem xét sự phản chiếu như là phương sách cuối cùng của tôi. Đặc biệt cho mục đích này. –
Điều gì về các khung công tác như JSf2.0 sử dụng chú thích? Chúng nên sử dụng các API phản chiếu để khởi tạo đối tượng trong thời gian chạy? – Ullas
Nếu đó là về JSF, thì vui lòng gắn thẻ là như vậy. –