2012-01-13 36 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

相关问题