Java 我可以用合成替换这个继承吗?
因此,让我们从一些背景开始[修改为更具体[。我意识到我可以替换以下内容:Java 我可以用合成替换这个继承吗?,java,oop,dependency-injection,Java,Oop,Dependency Injection,因此,让我们从一些背景开始[修改为更具体[。我意识到我可以替换以下内容: abstract class MessageHandler { public void handleMessage(Message m) { validateMessage(m); processMessage(m); } protected void validateMessage(Message m) { // Default validation logic } pro
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) {}
}
注入接口现在不能使用,因为MessageHandler中只有1个抽象方法。但是,我不能强制注入接口包含方法validateMessage(Message Message)
,因为使用抽象类的最初目的是定义此方法的默认实现
是否有某种优雅的模式将其转换为组合,以实现依赖注入和更简单的测试?以下是我的看法: 我没有扩展MessageHandler,而是有一个MessageHandler类,它是IMessageProcessor和IMessageValidator的组合: 希望我得到了正确的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接口,则它将用作验证器。这可能是您想要的,因为您可以使用相同的构造函数使用默认验证或自定义验证逻辑来构建MessageHandler,这取决于传入的对象是否仅实现IMessageProcessor或IMessageProcessor和IMessageValidator(为了方便起见,我从这些接口扩展了第三个接口,ivalidingMessageProcessor)。如果单独实现了验证器逻辑(仅实现IMessageValidator),则可以使用setValidator方法设置
无需扩展MessageHandler,因为您可以在处理程序之外实现处理和验证逻辑,可以单独实现,也可以在实现处理和验证的单个类中实现
以下是我使用过的课程,希望能有所帮助:
文本形式:
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);
}
public interface IValidatingMessageProcessor extends IMessageProcessor, IMessageValidator
{
}
public class FakeMessageProcessor implements IMessageProcessor
{
public void processMessage(Message m)
{
System.out.println("Using FakeMessageProcessor to process message " + m);
}
}
IMessageValidator.java:
public interface IMessageValidator
{
public void validateMessage(Message m);
}
public class FakeMessageValidator implements IMessageValidator
{
public void validateMessage(Message m)
{
System.out.println("Using FakeMessageValidator to validate message " + m);
}
}
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);
}
}
IValidatingMessageProcessor.java:
interface IMessageProcessor
{
public void processMessage(Message m);
}
public interface IValidatingMessageProcessor extends IMessageProcessor, IMessageValidator
{
}
public class FakeMessageProcessor implements IMessageProcessor
{
public void processMessage(Message m)
{
System.out.println("Using FakeMessageProcessor to process message " + m);
}
}
FakeMessageProcessor.java:
interface IMessageProcessor
{
public void processMessage(Message m);
}
public interface IValidatingMessageProcessor extends IMessageProcessor, IMessageValidator
{
}
public class FakeMessageProcessor implements IMessageProcessor
{
public void processMessage(Message m)
{
System.out.println("Using FakeMessageProcessor to process message " + m);
}
}
FakeMessageValidator.java:
public interface IMessageValidator
{
public void validateMessage(Message m);
}
public class FakeMessageValidator implements IMessageValidator
{
public void validateMessage(Message m)
{
System.out.println("Using FakeMessageValidator to validate message " + m);
}
}
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);
}
}
FakeMessageProcessorAndValidator.java:
public interface IMessageValidator
{
public void validateMessage(Message m);
}
public class FakeMessageValidator implements IMessageValidator
{
public void validateMessage(Message m)
{
System.out.println("Using FakeMessageValidator to validate message " + m);
}
}
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);
}
}
上述类的简单测试(仅输出内容):
输出:
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
以下是我对此的看法: 我没有扩展MessageHandler,而是有一个MessageHandler类,它是IMessageProcessor和IMessageValidator的组合: 希望我得到了正确的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接口,则它将用作验证器。这可能是您想要的,因为您可以使用相同的构造函数使用默认验证或自定义验证逻辑来构建MessageHandler,这取决于传入的对象是否仅实现IMessageProcessor或IMessageProcessor和IMessageValidator(为了方便起见,我从这些接口扩展了第三个接口,ivalidingMessageProcessor)。如果单独实现了验证器逻辑(仅实现IMessageValidator),则可以使用setValidator方法设置
无需扩展MessageHandler,因为您可以在处理程序之外实现处理和验证逻辑,可以单独实现,也可以在实现处理和验证的单个类中实现
以下是我使用过的课程,希望能有所帮助:
文本形式:
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);
}
public interface IValidatingMessageProcessor extends IMessageProcessor, IMessageValidator
{
}
public class FakeMessageProcessor implements IMessageProcessor
{
public void processMessage(Message m)
{
System.out.println("Using FakeMessageProcessor to process message " + m);
}
}
IMessageValidator.java:
public interface IMessageValidator
{
public void validateMessage(Message m);
}
public class FakeMessageValidator implements IMessageValidator
{
public void validateMessage(Message m)
{
System.out.println("Using FakeMessageValidator to validate message " + m);
}
}
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);
}
}
IValidatingMessageProcessor.java:
interface IMessageProcessor
{
public void processMessage(Message m);
}
public interface IValidatingMessageProcessor extends IMessageProcessor, IMessageValidator
{
}
public class FakeMessageProcessor implements IMessageProcessor
{
public void processMessage(Message m)
{
System.out.println("Using FakeMessageProcessor to process message " + m);
}
}
FakeMessageProcessor.java:
interface IMessageProcessor
{
public void processMessage(Message m);
}
public interface IValidatingMessageProcessor extends IMessageProcessor, IMessageValidator
{
}
public class FakeMessageProcessor implements IMessageProcessor
{
public void processMessage(Message m)
{
System.out.println("Using FakeMessageProcessor to process message " + m);
}
}
FakeMessageValidator.java:
public interface IMessageValidator
{
public void validateMessage(Message m);
}
public class FakeMessageValidator implements IMessageValidator
{
public void validateMessage(Message m)
{
System.out.println("Using FakeMessageValidator to validate message " + m);
}
}
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);
}
}
FakeMessageProcessorAndValidator.java:
public interface IMessageValidator
{
public void validateMessage(Message m);
}
public class FakeMessageValidator implements IMessageValidator
{
public void validateMessage(Message m)
{
System.out.println("Using FakeMessageValidator to validate message " + m);
}
}
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);
}
}
上述类的简单测试(仅输出内容):
输出:
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
在第二个例子中,
B
是否应该实现baz
而不是bar
?我也不确定我是否足够理解这个问题。是否可以尝试使其更具体?我认为解决方案已经到位,因为C
必须包含一个采用I
的构造函数(以便将其传递给基类)。我不理解你的问题。在A的第二个实现中,根本没有抽象方法,而不是你问题的最后一部分所说的1。你希望能够准确地做什么?我对代码进行了一些重构以使其更具可读性。例如,我将接口I
更改为IMessageProcessor
。请检查对于我犯的任何错误,希望代码现在更容易理解,您的问题也更容易回答。在第二个示例中,B
是否应该实现baz
而不是bar
?我也不确定我是否足够理解这个问题。是否可以尝试将其变得更具体?我认为解决方案已经存在位置,因为C
必须包含接受I
的构造函数(以便将其传递给基类)。我不理解你的问题。在A的第二个实现中,根本没有抽象方法,而不是问题的最后一部分所说的1。你希望能够准确地做什么?我对代码进行了一些重构,使其更具可读性。例如,我更改了接口I