英文:
Template Method: How to use it when you want to be able to flexibly change primitive options?
问题
The problem is best explained with the following code:
公开类 TemplateClass {
公开 void templateOne() {
检查条件A();
原始操作1();
检查条件B();
}
公开 void templateTwo() {
检查条件A();
原始操作2();
检查条件B();
}
受保护的抽象 void 原始操作1();
受保护的抽象 void 原始操作2();
// 其余方法
}
现在我在 templateOne() 和 templateTwo() 中有代码重复,但我希望只有一个模板方法,但原始操作可以互换。
英文:
The problem is best explained with the following code:
public class TemplateClass {
public void templateOne() {
checkConditionA();
primitiveOp1();
checkConditionB();
}
public void templateTwo() {
checkConditionA();
primitiveOp2();
checkConditionB();
}
protected abstract void primitiveOp1();
protected abstract void primitiveOp2();
// rest of the methods
}
Now I have code duplication with templateOne() and templateTwo(), but I would like to have just one template method but with interchangeable primitive operations.
答案1
得分: 2
你想要的实质上是在方法调用周围添加一个保护块。DRY编程是一个好的实践,但要注意不要将不应该耦合在一起的东西耦合在一起。只有在可以保证它们必须始终由相同的前置条件和后置条件保护时,我才会将这两个方法耦合在一起。
如果是这种情况,我建议实现一个方法 private void callWithChecks(Runnable primitiveOperation)
,然后将相应的原始操作作为参数传递给这个方法:
public abstract class TemplateClass {
public void templateOne() {
callWithChecks(this::primitiveOp1);
}
public void templateTwo() {
callWithChecks(this::primitiveOp2);
}
private void callWithCkecks(Runnable primitiveOperation) {
checkConditionA();
primitiveOperation.run();
checkConditionB();
}
protected abstract void primitiveOp1();
protected abstract void primitiveOp2();
// 其他方法
}
如果你不想使用函数接口 Runnable
,当然可以定义自己的接口。我选择它,因为它是一个Java基类。
关于你的代码有两点备注:
TempalteClass
必须声明为abstract
,否则代码将无法编译。- 如果你打算在
TemplateClass
中实现方法checkConditionA()
和checkConditionB()
,我建议将它们定义为private
或final
,以防止它们被覆盖。
英文:
What you want is, in essence, a guard block around a method call. DRY programming is good practice, but be advice that you do not wawnt to couple what should not be coupled. I would only couple those two methods if it is guaranteed that they must always be guarded by the same pre- and postcondition(s).
If this is the case, I would recommend to implement a method private void callWithChecks(Runnable primitiveOperation)
and then pass the respective primitive operation as parameter to this method:
public abstract class TemplateClass {
public void templateOne() {
callWithChecks(this::primitiveOp1);
}
public void templateTwo() {
callWithChecks(this::primitiveOp2);
}
private void callWithCkecks(Runnable primitiveOperation) {
checkConditionA();
primitiveOperation.run();
checkConditionB();
}
protected abstract void primitiveOp1();
protected abstract void primitiveOp2();
// rest of the methods
}
If you do not want to use the function interface Runnable
, you can of course define your own interface. I went with it, since it is a Java base class.
Two remarks on your code:
TempalteClass
must be declaredabstract
, otherwise the code will not compile- If you intend to implement methods
checkConditionA()
andcheckConditionB()
withinTemplateClass
, I would recommend defining them asprivate
orfinal
such that they cannot be overridden.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论