2015-01-28 20 views
6

Tôi có một lớp java trừu tượng "BaseOperation". Lớp này chỉ có một phương thức trừu tượng duy nhất:Một phương thức java có cả kiểu trả về biến và các đối số đầu vào biến đổi

public abstract T execute() 
{ 
    ... 

    return T; 
} 

lớp con của BaseOperation phải thực hiện phương pháp này:

public class GetUsersOperation extends BaseOperation<GetUsersResponse> 
{ 
    ... 

    @Override 
    public GetUsersResponse execute() 
    { 

     ... 

     return GetUsersResponse; 
    } 

} 

Đây là một cách tuyệt vời để đưa tất cả chung "hoạt động" logic trong lớp BaseOperation, nhưng vẫn có phương thức execute() của lớp con cụ thể có kiểu trả về khác nhau.

Bây giờ tôi cần phải thay đổi cấu trúc này để cho phép các phương thức execute() có số lượng đối số thay đổi. Ví dụ, một lớp con cụ thể sẽ yêu cầu:

execute(String, int) 

và khác sẽ cần:

execute(Date, Date, String) 

Đây là khó khăn, bởi vì phương thức execute được khai báo trong lớp cơ sở. Chỉ đơn giản là quá tải các phương thức thực hiện trong cơ sở là không lý tưởng. Thứ nhất, lượng quá tải sẽ rất lớn. Thứ hai, mọi phân lớp sẽ chỉ sử dụng một trong các phương thức thực hiện, điểm của tất cả các phương thức khác là gì?

The (theo ý kiến ​​của tôi) giải pháp dễ nhất sẽ được tuyên bố phương thức execute với varargs:

execute(Object... arguments) 

Và sau đó nhìn xuống tất cả các đối số trong các lớp con:

execute(Object... arguments) 
{ 
    String s = (String) arguments[0]; 
    ... 
} 

Rõ ràng đây có 2 lớn downsides:

  • Hiệu suất giảm do tất cả hoạt động downcasting
  • Gọi phương thức execute() không còn được nhập đúng vì bất kỳ lượng đối tượng nào có thể được thông qua cảnh báo trình biên dịch witout.

Có các mẫu hoặc giải pháp nào khác không thể có những nhược điểm này không?

Trả lời

2

Như đã nói, cách tiếp cận chung để giải quyết vấn đề của bạn là sử dụng thông số giữ đậu.Nhưng đây là một giải pháp khác, dựa trên phương pháp xây dựng:

public interface BaseOperation<T> { 
    public T execute(); 
} 

public class AddOperation implements BaseOperation<Integer> { 
    private int a, b; 

    public void setA(int arg){ 
    a = arg ; 
    return this; 
    } 

    public void setB(int arg){ 
    b = arg; 
    return this; 
    } 

    @Override 
    public Integer execute() { 
    return a+b ; 
    } 
} 

Và sau đó sử dụng nó như thế này:

new AddOperation().setA(1).setB(2).execute(); 

Bạn có thể trộn theo yêu cầu và thông số tùy chọn theo cách này:

public class MultipleAddOperation implements BaseOperation<Integer> { 
    private int sum ; 

    public MultipleAddOperation(int requiredInt){ 
    sum = requiredInt; 
    } 

    public void add(int optionalInt){ 
    sum += optionalInt ; 
    return this; 
    } 

    @Override 
    public Integer execute(){ 
    return sum; 
    } 
} 

Và như vậy:

new MultipleAddOperation(5).add(1).add(2).execute(); 
+0

Tôi thích cách logic của ông về đầu vào được yêu cầu được mã hóa thành các thuộc tính (các trường) của chính lớp con (với các phương thức thiết lập cần thiết), chứ không phải là một lớp bean riêng biệt. Tuy nhiên, không có gì ngăn cản tôi gọi hàm execute() mà không thiết lập các tham số appropiate. Điều này có thể được giải quyết? – user1884155

+0

@ user1884155 Có, chuyển đối số trong hàm tạo hoạt động, xem chỉnh sửa của tôi;) – NiziL

+0

Ah, hiển nhiên. Tôi thích giải pháp này trong giải pháp javabean 'đơn giản' vì tất cả các tham số của tôi là bắt buộc và tôi không muốn giới thiệu một lớp bean bổ sung cho mọi lớp hoạt động mà tôi tạo ra. Cảm ơn! – user1884155

5

Bạn có thể sử dụng một bean giữ các thông số:

public interface BaseOperation<T, U> { 
    T execute(U input); 
} 

public class GetUsersOperation implements BaseOperation<GetUsersResponse, UserInput> { 

    @Override 
    public GetUsersResponse execute(UserInput input) { 
     Date date = input.getDate(); 
     return new GetUsersResponse(date); 
    } 

} 

lớp trừu tượng của bạn chỉ có một phương pháp trừu tượng duy nhất: sử dụng tốt hơn một giao diện. Bạn có thể thực hiện một số giao diện trong khi bạn chỉ có thể mở rộng một lớp.

+0

Cảm ơn bạn đã pr trả lời ompt. Lớp cơ sở của tôi có các phương thức khác, nhưng nó chỉ có 1 phương thức PUBLIC. Tất cả các phương thức private/protected khác không trừu tượng và làm các công việc phổ biến như đăng nhập, phân tích cú pháp tin nhắn, vv Giao diện không thể có mã thực trong java 1.7 vì vậy tôi nghĩ việc chuyển nó sang giao diện là không thể. Hay tôi sai về chủ đề này? – user1884155

+0

@ user1884155 Không, bạn nói đúng, tôi nghĩ nó chỉ có một phương pháp trừu tượng duy nhất. – sp00m

+1

Tò mò là tại sao người ta thích một loại đậu hơn là chỉ một lớp với nhiều nhà thầu? Với các nhà xây dựng quá tải, bạn có thể tránh tất cả các dòng bổ sung thiết lập các tham số, và cũng cung cấp một số dấu hiệu của các kết hợp tham số có thể chấp nhận được và các giá trị được yêu cầu. – Blegger

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