2015-12-09 15 views
5

Tôi đang vật lộn một chút với tính năng truyền lớp. Để tôi đặt cảnh. Tôi có mã máy chủ java sử dụng một lớp dịch vụ và dàn nhạc. Một yêu cầu đi vào lớp dịch vụ trong một định dạng bean (lớp java liên kết với khung nhìn front end), và sau đó tôi có một loạt các lớp domainBeanMapper lấy một đối tượng định dạng bean và dịch nó thành một đối tượng định dạng miền. Ví dụ: UserBean có một dateOfBirth được biểu diễn bằng một chuỗi, trong khi User có dateOfBirth được biểu diễn bởi một Date để UserMapper.java sẽ làm cho chuỗi ngày tháng thành một đối tượng ngày tháng. Vì vậy, đối với mỗi đối tượng trong hệ thống, tôi có * .java, * Bean.java và * Mapper.java (User.java, UserBean.java, userMapper.java).Java - truyền tới giao diện, sau đó tìm hiểu loại được đúc là

trong applicationContext tôi giữ mối quan hệ của từng đối tượng để ánh xạ của họ, như thế này:

<util:map id="domainBeanMappers"> 
    <entry key="UserBean" value-ref="userMapper" /> 
    <entry key="User" value-ref="userMapper" /> 
..... 

và sau đó tôi xác định mapper:

<bean id="userMapper" class="com.me.mapping.UserMapper" parent="baseDomainBeanMapper"/> 

tôi gọi là người vẽ bản đồ đậu miền như thế này từ lớp dịch vụ của tôi:

UserBean userBean = (UserBean) getDomainBeanMapper().mapDomainToBean(user); 

Khi chạy mã này tôi tìm thấy người lập bản đồ ct mà tôi muốn như thế này:

DomainBeanMapper mapper = findApplicableMapper(myObject.getClass().getName()); 
    if (mapper == null) { 
     mapper = findApplicableMapper(myObject.getClass().getSimpleName()); 
    } 

nơi findApplicableMapper làm việc như thế này:

private DomainBeanMapper findApplicableMapper(String string) { 
    return domainBeanMappers.get(string); 
} 

Trong vài năm trở lại đây, điều này đã làm việc như một nét duyên dáng. Đối với bất kỳ đối tượng nào tôi muốn trong hệ thống, tôi có thể dễ dàng chọn ra trình ánh xạ có liên quan và sau đó dịch từ định dạng bean sang định dạng miền và ngược lại, dựa trên cuộc gọi .getClass() của bất kỳ cá thể nào.

Bây giờ, tôi có một yêu cầu mới khiến tôi gặp rắc rối. Tôi muốn có thể dịch từ đối tượng User của tôi sang một số đối tượng phụ dựa trên tham số. Vì vậy, đối với một số cuộc gọi, tôi chỉ muốn id, firstName và lastName trở lại. Đối với các cuộc gọi khác, tôi muốn nhiều trường hơn, nhưng vẫn không phải toàn bộ đối tượng, và sau đó đối với một số cuộc gọi, tôi muốn toàn bộ đối tượng quay lại như trước đây. Tôi không muốn đi xuống con đường phụ đối tượng và kết thúc với UserLight, UserLightWithName, UserLightWithNameButNoAddress, ... argh nightmare.

Vì vậy, thay vào đó, tôi đã hy vọng tạo ra một loạt giao diện đại diện cho "lượt xem". Vì vậy, yêu cầu đến với ViewType of Basic và điều đó có nghĩa là tôi muốn chi tiết và địa chỉ cá nhân của người dùng. Vì vậy, tôi đã viết một giao diện được gọi UserBasic, có tài khoản để thực hiện nó, và thêm một ánh xạ từ UserBasic để UserBasicMapper, và từ UserBasicBean để UserBasicMapper, với hy vọng rằng tôi có thể thực hiện cuộc gọi dịch như thế này:

UserBasicBean restrictedUserReturn = (UserBasicBean) getDomainBeanMapper().mapDomainToBean((UserBasic)user); 

nhưng điều này không làm việc vì getClass() luôn luôn trả về lớp cá thể, không phải là giao diện mà nó đã được đưa vào. Tôi đoán tôi luôn có thể thêm một paramater khác cho cuộc gọi mapDomainToBean là lớp mà tôi muốn sử dụng, nhưng codebase khá lớn và tôi sẽ cần phải chạm vào mọi cuộc gọi nếu tôi thực hiện thay đổi đó.

Vì vậy, về cơ bản tôi đang tìm cách để truyền một thể hiện sang loại giao diện và sau đó tìm loại giao diện đó? Điều này có thể không?

thánh ngón tay ...

+0

Tại sao bạn không muốn toàn bộ đối tượng? –

+0

đó là yêu cầu bảo mật. một số người dùng nhất định của hệ thống chỉ có thể thấy một số phần nhất định của đối tượng. – Margaret

Trả lời

3

Thay vì tạo giao diện mà người dùng thực hiện, tại sao không tạo các lớp proxy đại diện cho các phiên bản giới hạn? Ví dụ:

class UserBasic { 

    private User user; 

    public UserBasic(User user) { 
     this.user = user; 
    } 

    public String getFirstName() { 
     return user.getFirstName(); 
    } 
    ... 
} 

Sau đó, bạn có thể thêm getUser() { return user; } để lấy lại toàn bộ cá thể.

Bằng cách này bạn sẽ có thể giữ mọi thứ khác giống nhau và thực hiện giao dịch cho lớp trên giao diện.

+1

Ooh, điều này thật tuyệt !!! Nó sẽ giúp tôi có cùng chức năng và tôi sẽ không phải thay đổi mã domainBeanMapper. UserBasic cũng có thể có một phương thức getUser() để cho phép tôi ánh xạ theo một hướng khác - cho các yêu cầu cung cấp khung nhìn đối tượng phụ. Vâng, điều này thật tuyệt! – Margaret

+0

ha, tuyệt vời, bạn đã thêm phần getUser khi tôi đang viết bình luận của mình.Cảm ơn bạn rất nhiều vì đã dành thời gian cho bạn! – Margaret

+1

Rất vui được trợ giúp !! @Margaret – ChiefTwoPencils

0

Tôi không chắc chắn nhưng bạn có thể sử dụng instanceof từ khóa để kiểm tra những loại đối tượng nó được.

+1

tiếc là đó là không thực sự sẽ làm việc như tôi sẽ phải nói \t if (myObject instanceof UserBasic) { \t \t mapper = findApplicableMapper ("UserBasic"); \t} else if (myObject instanceof AnotherView) { \t \t ..... \t} mà sẽ thực sự bẩn lên mã của tôi. cảm ơn cho suy nghĩ mặc dù. – Margaret

+0

những gì tôi đang tìm kiếm là một cách để tận dụng lợi thế của mã đằng sau việc thực hiện instanceOf để tìm hiểu myObject là gì. nó có vẻ ngớ ngẩn rằng điều này sẽ không có sẵn – Margaret

0

Bạn có thể làm một cái gì đó giống như viết vài phương pháp khác nhau với các loại paramenter, ví dụ:

public class Test 
{ 

    public static void n(Number n) { 
     System.out.println("Number"); 
    } 

    public static void n(Integer n) { 
     System.out.println("Integer"); 
    } 

    public static void main(String[] args) 
    { 
     n(3); //will call the n(Integer n); 
     n((Number)3); //will call the n(Number n); 
    } 
} 

Vì vậy, có, bạn có thể tìm hiểu mà gõ bạn đã Casted đến bằng cách làm cho nhiều phương pháp từng dùng loại tham số thích hợp và sau đó xử lý nó cho phù hợp để gõ.

+0

tiếc là tôi không tin rằng tôi có thể sử dụng con đường này. Tôi sẽ có đối tượng của tôi thực hiện nhiều giao diện cho các khung nhìn khác nhau. Tất cả sẽ là tập hợp chồng chéo của các getters và setters có liên quan của các biến thành viên. ví dụ. Người dùng triển khai UserBasic, UserLight, UserLocation. sau đó nếu tôi sử dụng kiểm tra instanceof, nó sẽ trả về true cho tất cả chúng khi đối tượng User thực hiện tất cả chúng. thay vì kiểm tra loại tôi vừa truyền đến. Điều đó có ý nghĩa không? Tôi cần phải tìm ra giao diện cụ thể vừa được truyền. – Margaret

0

Giao diện không đại diện cho chế độ xem - nó xác định hành vi. Tôi đoán bạn cần một số loại nhà máy (ckech những liên kết này để tìm cảm hứng https://en.wikipedia.org/wiki/Factory_method_pattern, https://sourcemaking.com/design_patterns/abstract_factory) ở đây (hoặc xây dựng) Nếu bạn nói điều gì đó về 'tiểu đối tượng' - cố gắng mở rộng lớp UserBean

class BaseUserBean extends UserBean {} 
class AnotherUserBean extends UserBean {} 

đặt các công cụ phổ biến cho mọi người dùng vào lớp base và một cái gì đó thực sự cụ thể cho từng tiểu người dùng của bạn giả sử vào các lớp học trẻ em và sau đó

UserBean u = getDomainBeanMapper().mapDomainToBean(user); 

...

//method mapToDomain should check your param and return the type you need 
//ViewType can be a part of user or a separate param 
UserBean mapDomainToBean(User user, ViewType vt) { 
    if (vt == ViewType.BASE) { 
     BaseUserBean obj = BaseUserBean(); 
     // mapping here (set fields you need) 
     return obj; 
    } 

    if (vt == ViewType.ANOTHER) { 
     AnotherUserBean obj = AnotherUserBean(); 
     // mapping here (set fields you need) 
     return obj; 
    } 
    ... 
} 
+0

điều này là chắc chắn có thể, cảm ơn bạn, nhưng việc thay đổi chữ ký mapDomainToBean sẽ ảnh hưởng đến hàng trăm điểm và hiện không có thời gian để kiểm tra hồi quy toàn bộ hệ thống quá cẩn thận. – Margaret

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