2012-01-13 71 views
0

所以,讓我們先從一些背景修改,使其更加具體[。我已經意識到我可以替換以下:我可以用組合來代替這個繼承嗎?

abstract class MessageHandler { 
    public void handleMessage(Message m) { 
    validateMessage(m); 
    processMessage(m); 
    } 

    protected void validateMessage(Message m) { 
    // Default validation logic 
    } 

    protected abstract void processMessage(Message m); 
} 

class FakeMessageHandler extends MessageHandler { 
    proteced void processMessage(Message m) {} 
} 

與下一個代碼塊:

interface IMessageProcessor { 
    public void processMessage(Message m); 
} 

class FakeMessageProcessor implements IMessageProcessor { 
    public void processMessage(Message m) {} 
} 

class MessageHandler { 
    private IMessageProcessor processor; 
    public MessageHandler(IMessageProcessor processor) { 
    this.processor = processor; 
    } 

    public void handleMessage(Message message) { 
    validateMessage(message); 
    processor.processMessage(message); 
    } 

    protected void validateMessage(Message message) { 
    // Default validation logic. 
    } 
} 

即,我可以用注射接口代替抽象方法,以便更容易測試。現在,讓我們說,設計規定,人們可以選擇覆蓋的方法:

class FakeMessageHandler extends MessageHandler { 
    protected void validateMessage(Message m) {} 
    protected void processMessage(Message m) {} 
} 

注入的界面現在還不能使用,因爲只有1中的MessageHandler抽象方法。然而,我不能強制注入的接口包含方法validateMessage(Message message),因爲使用抽象類的原始點是定義此方法的默認實現。

是否有某種優雅的圖案以這種轉換成組成依賴注入,更容易測試的目的是什麼?

+0

在第二個例子,不應該'B'執行'baz'而不是'bar'?我不確定我是否足夠了解這個問題。是否有可能嘗試使其更具體?我認爲解決方案已經到位,因爲'C'必須包含一個構造函數,它需要一個'I'(以便將它傳遞給基類)。 – 2012-01-13 09:04:46

+0

我不明白你的問題。在A的第二個實現中,根本不存在抽象方法,而不是問題的最後一部分。你想要做什麼? – 2012-01-13 09:28:07

+0

我重構了代碼,使其更具可讀性。例如,我將接口'I'改爲'IMessageProcessor'。請檢查我所做的任何錯誤,但希望代碼現在更容易遵循,並且您的問題更容易回答。 – Steven 2012-01-13 13:05:14

回答

4

這裏是我拿到這個:

而是延伸MessageHandler的,我有一個單一的MessageHandler類,即IMessageProcessor的組成和IMessageValidator: Class diagram

希望我得到了UML-圖沒錯,它已經有一段時間...

無論如何,讓我們一起來看看的MessageHandler:


class MessageHandler 
{ 
    private IMessageProcessor processor; 
    private IMessageValidator validator; 

    public MessageHandler(IMessageProcessor processor) 
    { 
     this.processor = processor; 

     //Use the given processor as validator, if it implements the IMessageValidator-interface 
     if(IMessageValidator.class.isAssignableFrom(processor.getClass())) 
     { 
      this.validator = (IMessageValidator)processor; 
     } 
    } 

    public void setMessageValidator(IMessageValidator validator) 
    { 
     this.validator = validator; 
    } 

    public void handleMessage(Message message) 
    { 
     validateMessage(message); 
     processor.processMessage(message); 
     System.out.println("Message " + message + " handled by MessageHandler"); 
    } 

    protected void validateMessage(Message message) 
    { 
     if(validator != null) 
     { 
      validator.validateMessage(message); 
     } 
     else 
     { 
      System.out.println("No IMessageValidator-implementation set, using default validation for message " + message); 
     } 
    } 
} 

MessageHandler的具有兩個私有成員,IMessageProcessor和IMessageValidator(它是一個處理器和一個校驗的組合物)。驗證器可以不設置,在這種情況下,默認驗證邏輯將在處理消息時啓動。

在這個例子中,如果傳入的處理器也實現了IMessageValidator接口,它將被用作驗證器。這可能是你想要的,因爲你可以使用相同的構造來構建使用默認的驗證或自定義的驗證邏輯MessageHandlers,取決於如果傳入的對象只實現IMessageProcessor或IMessageProcessor和IMessageValidator都(爲方便起見,我已延長第三接口,來自這些接口的IValidatingMessageProcessor)。如果驗證器邏輯單獨實現(僅實現IMessageValidator),則可以使用setValidator方法進行設置。

有沒有需要延長的MessageHandler,你可以處理程序之外同時實現處理和驗證編輯邏輯,單獨或在同時實現處理和驗證的類。

下面是我用的類,希望這有助於:

Zip-package in MediaFire

文本形式:

Message.java:


public class Message 
{ 
    private int number; 

    public Message(int number) 
    { 
     this.number = number; 
    } 

    public String toString() 
    { 
     return "Msg " + number; 
    } 
} 

IMessageProcessor。Java的:


interface IMessageProcessor 
{ 
    public void processMessage(Message m); 
} 

IMessageValidator.java:


public interface IMessageValidator 
{ 
    public void validateMessage(Message m); 
} 

IValidatingMessageProcessor.java:


public interface IValidatingMessageProcessor extends IMessageProcessor, IMessageValidator 
{ 
} 

FakeMessageProcessor.java:


public class FakeMessageProcessor implements IMessageProcessor 
{ 
    public void processMessage(Message m) 
    { 
     System.out.println("Using FakeMessageProcessor to process message " + m); 
    } 
} 

FakeMessageValidator.java:


public class FakeMessageValidator implements IMessageValidator 
{ 
    public void validateMessage(Message m) 
    { 
     System.out.println("Using FakeMessageValidator to validate message " + m);  
    } 
} 

FakeMessageProcessorAndValidator.java:


public class FakeMessageProcessorAndValidator implements IValidatingMessageProcessor 
{ 
    public void validateMessage(Message m) 
    { 
     System.out.println("Using FakeMessageProcessorAndValidator for validating message " + m); 
    } 

    public void processMessage(Message m) 
    { 
     System.out.println("Using FakeMessageProcessorAndValidator for processing message " + m);  
    } 
} 

簡單的測試主要用於上述類(只是輸出的東西):


public class MessageTest 
{ 
    public static void main(String[] args) 
    { 
     //Using processor implementing only IMessageProcessor, MessageHandler will use default validation 
     IMessageProcessor processor = new FakeMessageProcessor(); 
     MessageHandler handler = new MessageHandler(processor); 

     handler.handleMessage(new Message(1)); 

     //Setting separate validator to existing MessageHandler-instance 
     handler.setMessageValidator(new FakeMessageValidator()); 

     handler.handleMessage(new Message(2)); 

     //Using processor implementing both IMessageProcessor and IMessageValidator 
     processor = new FakeMessageProcessorAndValidator(); 
     handler = new MessageHandler(processor); 

     handler.handleMessage(new Message(3)); 
    } 
} 

輸出:


No IMessageValidator-implementation set, using default validation for message Msg 1 
Using FakeMessageProcessor to process message Msg 1 
Message Msg 1 handled by MessageHandler 
Using FakeMessageValidator to validate message Msg 2 
Using FakeMessageProcessor to process message Msg 2 
Message Msg 2 handled by MessageHandler 
Using FakeMessageProcessorAndValidator for validating message Msg 3 
Using FakeMessageProcessorAndValidator for processing message Msg 3 
Message Msg 3 handled by MessageHandler 
+0

+1大小問題的答案 – Bohemian 2012-01-15 11:45:25

+0

我喜歡你如何處理默認實現的想法。不幸的是,我認爲它不能很好地擴展 - 如果有3種方法可以選擇重寫,會發生什麼?我想我一直希望有一個通用的解決方案,但我會將你的標記標記爲正確,因爲它可能是我將要得到的最接近的。謝謝! – Bringer128 2012-01-16 00:26:57

相關問題