2017-01-26 6 views
10

में वैकल्पिक विधि कार्यान्वयन मैं कुछ ढांचे पर काम कर रहा हूं और मुझे एक अमूर्त वर्ग मिला है, जिसे कार्यान्वित किया जाना चाहिए।एक अमूर्त वर्ग

अब मुझे कुछ अन्य सामान मिल गया है जो उपयोगकर्ता को कॉन्फ़िगर करने में सक्षम होना चाहिए, लेकिन यह वैकल्पिक है।

तो बजाय सार विधि:

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(); 
} 

मैं सिर्फ एक अंतरफलक कार्यान्वयन के लिए जाँच के बारे में सोचा:

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(); 
} 

तो, अगर किसी को इंटरफेस के साथ AbstractModule लागू कर रहा है लॉग इन करें यह भी पता चलेगा संदेश। कार्यान्वयनकर्ता के लिए लाभ जो मैं देखता हूं: उसे logMessage() को लागू करने की परवाह करने की आवश्यकता नहीं है, क्योंकि यह पहले उदाहरण में होगा। क्या यह एक वैध दृष्टिकोण है या इसे अलग-अलग किया जाना चाहिए?

अग्रिम धन्यवाद!

सादर

उत्तर

4

मैं लॉगर अपने मॉड्यूल का एक घटक बनाने के लिए और अमूर्त वर्ग में लकड़हारा एक डिफ़ॉल्ट कोई सेशन को परिभाषित करेगा। इस तरह आप instanceof से छुटकारा पाएं और अभी भी लचीलापन बचाएं।

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(); 
} 

यहाँ एक उदाहरण वर्ग का विस्तार AbstractModule है:

public class Module extends AbstractModule{ 

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

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

} 

आप अमूर्त वर्ग में लकड़हारा के लिए एक गेटर-विधि परिभाषित कर सकते हैं अगर आप लकड़हारा बेनकाब करने के लिए करना चाहते हैं:

public Log getLogger(){ 
    return log; 
} 
2

instanceof के लिए पहुंचने से कोई कोड गंध का एक सा है, ऐसा करने का आमतौर पर एक बेहतर तरीका है।

मेरी पहली वृत्ति आधार वर्ग में नो-सेशन विधि है:

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

    void maybeLogMessage() {} 
} 

जो स्पष्ट रूप से कुछ नहीं करता है; लेकिन फिर आप एक उपवर्ग में ओवरराइड कर सकते हैं:

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

जो संदेश मुद्रित होगा।

यदि आप सभी सबक्लास में System.out.println दोहराना नहीं चाहते हैं, तो आप यह इंगित करने के लिए विधि से एक विशेष मान वापस कर सकते हैं कि इसे लॉग नहीं किया जाना चाहिए। उदाहरण के लिए, आप स्ट्रिंग की आवश्यकता होती है खाली नहीं होना करने के लिए कर सकते हैं:

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

चूंकि इस प्रश्न को java-8 के रूप में टैग किया गया है, इसलिए एक वैकल्पिक समाधान interface और default विधियों का उपयोग करना होगा:

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(); 
} 

उपयोग:

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

class LogModule implements Module { 

    @Override 
    public void doStuff() { } 

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

} 

एक एक सार वर्ग के बजाय इस दृष्टिकोण का उपयोग करने का लाभ यह है कि अपने वर्ग अब एक और वर्ग से विस्तार करने के लिए नि: शुल्क है। इस दृष्टिकोण का एक नुकसान यह है कि doSomething विधि (आपके कोड के आधार पर, ऐसा लगता है कि आप इस पर ध्यान नहीं देते हैं)

से किसी को रोकने के लिए आप कुछ भी नहीं कर सकते हैं
संबंधित मुद्दे