2017-01-26 16 views
10

Tôi đang làm việc trên một số khung công tác và tôi có một lớp trừu tượng, nên được triển khai.Triển khai phương pháp tùy chọn trong lớp trừu tượng

Bây giờ tôi có một số nội dung khác mà người dùng có thể định cấu hình, nhưng nó là tùy chọn.

Vì vậy, thay vì phương pháp trừu tượng:

public abstract class AbstractModule { 
    public void doSomething() { 
     if (logMessage() != null) 
      System.out.println(logMessage()); 
     doStuff(); 
    } 

    protected abstract String logMessage(); // I'm optional 
    protected abstract void doStuff(); 
} 

tôi nghĩ chỉ kiểm tra cho một thực hiện giao diện:

public interface Log { 
    String logMessage(); 
} 

public abstract class AbstractModule { 
    public void doSomething() { 
     if (this instanceof Log) { 
      if (((Log) this).logMessage() != null) 
       System.out.println(((Log) this).logMessage()); 
     } 
     doStuff(); 
    } 

    protected abstract void doStuff(); 
} 

Vì vậy, nếu một người nào đó đang thực hiện AbstractModule với giao diện đăng nhập nó cũng sẽ hiển thị thông điệp. Lợi ích cho người triển khai mà tôi thấy: Cô ấy không cần quan tâm đến việc thực hiện logMessage(), vì nó sẽ là ví dụ đầu tiên. Đây có phải là một cách tiếp cận hợp lệ hoặc nó nên được thực hiện khác nhau?

Cảm ơn trước!

Trân trọng

Trả lời

4

Tôi sẽ làm cho Logger trở thành thành phần của mô-đun và xác định trình ghi mặc định không có trong lớp trừu tượng. Bằng cách này, bạn thoát khỏi instanceof và vẫn duy trì tính linh hoạt.

interface Log { 
    void logMessage(); 
} 

public abstract class AbstractModule { 
    protected Log log; 

    public AbstractModule(){ 
     this.log =() -> {}; 
    } 

    public AbstractModule(Log log){ 
     this.log = log; 
    } 

    public void doSomething() {   
     log.logMessage();   
     doStuff(); 
    } 

    protected abstract void doStuff(); 
} 

Dưới đây là một lớp dụ mở rộng AbstractModule:

public class Module extends AbstractModule{ 

    public Module(){ 
     super(() -> System.out.println("message"));   
    } 

    @Override 
    protected void doStuff() { 
     // do stuff  
    } 

} 

Bạn có thể định nghĩa một getter-phương pháp cho logger trong lớp trừu tượng nếu bạn muốn để lộ các logger:

public Log getLogger(){ 
    return log; 
} 
2

Tiếp cận với instanceof có một chút mùi mã; thường có cách làm tốt hơn.

bản năng đầu tiên của tôi là phải có một phương pháp không-op trong lớp cơ sở:

class AbstractModule { 
    final void doSomething() { 
    maybeLogMessage(); 
    } 

    void maybeLogMessage() {} 
} 

mà rõ ràng là không có gì; nhưng sau đó bạn có thể ghi đè lên một phân lớp:

class Subclass extends AbstractModule { 
    @Override void maybeLogMessage() { 
    System.out.println("The message"); 
    } 
} 

sẽ in thông báo.

Nếu bạn không muốn lặp lại System.out.println trong tất cả các lớp con, bạn có thể trả về một giá trị đặc biệt từ phương thức để cho biết rằng nó không được ghi nhật ký. Ví dụ: bạn có thể yêu cầu chuỗi không trống:

class AbstractModule { 
    final void doSomething() { 
    String message = logMessage(); 
    if (!message.isEmpty()) { System.out.println(message); } 
    } 

    String logMessage() { return ""; } 
} 

class Subclass extends AbstractModule { 
    @Override String logMessage() { 
    return "The message"; 
    } 
} 
4

Vì câu hỏi này đã được gắn thẻ là java-8, một giải pháp thay thế sẽ là sử dụng phương thức interfacedefault:

public interface Module { 
    public default void doSomething() { 
     if (logMessage() != null) 
      System.out.println(logMessage()); 
     doStuff(); 
    } 

    public default String logMessage() { return null; } // I'm optional 
    public void doStuff(); 
} 

Cách sử dụng:

class NoLogModule implements Module { 
    @Override 
    public void doStuff() { } 
} 

class LogModule implements Module { 

    @Override 
    public void doStuff() { } 

    @Override 
    public String logMessage() { return "Message "; } 

} 

Một lợi thế của việc sử dụng phương pháp này thay vì một lớp Tóm tắt là lớp của bạn bây giờ là miễn phí để mở rộng từ một lớp khác. Một bất lợi của phương pháp này là bạn không thể làm gì để ngăn ai đó từ ghi đè phương thức doSomething (Dựa trên mã của bạn, có vẻ như bạn không quan tâm đến điều này)

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