2013-08-25 64 views
12

Thực tiễn tốt là sử dụng Mô hình phản chiếu trong Nhà máy?Sử dụng Phản chiếu trong mẫu nhà máy

public class MyObjectFactory{ 
private Party party; 

public Party getObject(String fullyqualifiedPath) 
{ 
    Class c = Class.forName(fullyqualifiedPath); 
    party = (PersonalParty)c.newInstance(); 
    return party; 
} 
} 

PersonalParty thực hiện Đảng

+1

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. –

+0

Đ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

+1

Nếu đó là về JSF, thì vui lòng gắn thẻ là như vậy. –

Trả lời

9

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.

+0

Cảm ơn lời giải thích chi tiết .. – Ullas

+0

@Ullas - Niềm vui của tôi. Thêm một đoạn nữa nhấn mạnh khi bạn nên sử dụng các giải pháp phản chiếu so với khi bạn nên sử dụng 'AsbtractFactory'. –

1

Sử dụng phản ánh nó theo cách này (Class.forName) là hầu như luôn đăng của thiết kế ứng dụng xấu. Có một số loại, nơi sử dụng của nó là OK, ví dụ nếu bạn đang làm một số loại tải động của thư viện bên ngoài hoặc bổ sung.

1

Bạn có thể sử dụng nó cho API nơi bạn cung cấp API và cấu hình XML nơi người dùng có thể thêm tên lớp của plugin của họ. Sau đó, có, bạn có thể sử dụng này