我遇到了一个扩展给定类功能的情况,但我不确定最好的方法.我开始调用"向上"功能,现在切换到"向下",但我看到两者都有问题.让我解释一下我的意思.首先,"向上"的方法:
public class ParentValidator
{
public void validate() {
// Some code
}
}
public class ChildValidator extends ParentValidator
{
@Override
public void validate() {
super.validate();
// Some code
}
}
public class GrandchildValidator extends ChildValidator
{
@Override
public void validate() {
super.validate();
// Some code
}
}
Run Code Online (Sandbox Code Playgroud)
这个功能非常好,但它要求我总是记得在我的方法体中放置super.validate()或者不会执行父类中的逻辑.此外,由于子类实际上可以替换/修改父类中定义的代码,因此以这种方式扩展可以被认为是"不安全的".这就是我称之为"向上"调用方法的原因,因为我正在调用更高级别的方法.
为了解决这些不足,我决定让ParentValidator.validate()最终并让它调用一个不同的方法.这是我的代码被修改为:
public class ParentValidator
{
public final void validate() {
// Some code
subValidate();
}
protected void subValidate() {}
}
public class ChildValidator extends ParentValidator
{
@Override
public final void subValidate() {
// Some code
subSubValidate();
}
protected void subSubValidate() {}
}
public class GrandchildValidator extends ChildValidator
{
@Override
public void subSubBalidate() {
// Some code
subSubSubValidate();
}
protected void subSubSubValidate();
}
Run Code Online (Sandbox Code Playgroud)
这就是我所说的当我说我向下调用时,因为每个类调用继承链"向下"类的方法.
使用这种方法,我可以保证将执行父类中的逻辑,我喜欢.但是,它不能很好地扩展.我拥有的层次越多,它就越丑陋.在某种程度上,我觉得这很优雅.在两个层面上,它开始变得粗制滥造.在三个或更多,它是可怕的.
另外,就像我必须记得调用super.validate()作为我孩子的任何验证方法的第一行一样,我现在必须记住在我父亲的任何验证方法的末尾调用一些"subValidate"方法. ,所以似乎没有变得更好.
有没有更好的方法来进行我甚至没有涉及的这种类型的扩展.这两种方法都有一些严重的缺陷,我想知道我是否有更好的设计模式.
在您所描述的第一种方法中,您使用的是简单继承,第二种方法更接近四人帮[GoF] 所谓的模板方法模式,因为您的父类正在使用所谓的好莱坞原则:“不要给我们打电话,我们就会给您打电话”。
但是,您可以通过在父类中将 subvalidate() 方法声明为抽象方法来受益,这样可以确保所有子类都强制实现它。那么这将是一个真正的模板方法。
public abstract class ParentValidator
{
public final void validate() {
//some code
subValidate();
}
protected abstract void subValidate() {}
}
Run Code Online (Sandbox Code Playgroud)
根据您正在做的事情,还有其他模式可以帮助您以不同的方式完成此任务。例如,您可以使用策略模式来执行验证,并且通过这种方式有利于组合而不是继承,如之前所建议的,但结果是您将需要更多的验证类。
public abstract class ParentValidator
{
private final ValidatorStrategy validator;
protected ParentValidator(ValidatorStrategy validator){
this.validator = validator;
}
public final void validate() {
//some code
this.validator.validate();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以为您拥有的每种类型的验证器提供特定的验证策略。
如果您想两全其美,您可能会考虑将解决方案实现为装饰器模式,其中子类可以扩展父类的功能,但仍然坚持通用接口。
public abstract class ValidatorDecorator implements Validator
{
private final Validator validator;
protected ParentValidator(Validator validator){
this.validator = validator;
}
public final void validate() {
//some code
super.validate(); //still forced to invoke super
this.validator.validate();
}
}
Run Code Online (Sandbox Code Playgroud)
所有模式都有后果和优点和缺点,您必须仔细考虑。
| 归档时间: |
|
| 查看次数: |
1281 次 |
| 最近记录: |