我的问题是:
我有这样的班级结构:
class Base
{
private:
SomeType something;
bool isSomeValue;
public:
virtual void myMethod() = 0;
};
class Child1 : public Base
{
virtual void myMethod() override
{
// do step 1
for (int i = 0; i < something.size(); ++i)
{
// do step 2
if (isSomeValue)
{
// do step 3
}
}
// do step 4
}
};
class Child2 : public Base
{
virtual void myMethod() override
{
// do step 1
for (int i = something.size() - 1; i >= 0; --i)
{
// do step 2
if (isSomeValue)
{
// do step 3
}
}
// do step 4
}
};
class Child3 : public Base
{
virtual void myMethod() override
{
// do step 1
for (int i = 0; i < something.size(); ++i)
{
// do step 2
if (isSomeValue)
{
// do step 3
}
else
{
break;
}
}
// do step 4
}
};正如您在Child2和Child3中所看到的,与Child1不同的是,Child2循环从相反的方向发展,而在Child3中,也有else和break语句。我希望您同意,这些算法只是略有不同,我几乎代码复制。对于这种类似的结构,是否有更好的方法来避免在许多不同的地方编写类似的代码?
这里是我想使用的干原理,虽然我不做代码复制,但是只编写类似的代码。我只是在几个类中看到了类似的构造。使用巧妙的模板法模式能消除类似的代码吗?或者其他方法?
发布于 2016-03-22 15:57:37
我要开始重构共同的部分,而不是不同的部分:
class Base
{
protected:
SomeType something;
bool isSomeValue;
void step1();
void step2(int i);
void step3IfSomeValue(int i);
void step4();
public:
virtual void myMethod() = 0;
};
class Child1 : public Base
{
virtual void myMethod() override
{
step1();
for (int i = 0; i < something.size(); ++i)
{
step2(i);
step3IfIsSomeValue(i);
}
step4();
}
};
class Child2 : public Base
{
virtual void myMethod() override
{
step1();
for (int i = something.size() - 1; i >= 0; --i)
{
step2(i);
step3IfIsSomeValue(i);
}
step4();
}
};
class Child3 : public Base
{
virtual void myMethod() override
{
step1();
for (int i = 0; i < something.size(); ++i)
{
step2(i);
step3IfIsSomeValue(i);
if (!isSomeValue)
break;
}
step4();
}
};当然,作为第二步,通过一些努力,您实际上可以将这三个方法概括为一个方法,正如@JoulinRouge所指出的(请注意,这没有显示模板方法模式)。
但是,您必须考虑这是否确实改善了您的代码。扪心自问:如果你必须增加一些额外的特性,因为你在三种方法中有“相似的部分”,但只有一种,这是否真的有被遗忘的风险呢?或者是相反的事实:是否因为你把三种方法概括为一种,而现在你不能再单独地改变它们,就很难改变什么?如果你能回答这个问题,你就知道该怎么做。
发布于 2016-03-22 14:31:24
像这样的怎么样?
void myMethod(Boolean reverse, Boolean doElse)
{
// do step 1
int start = 0;
int stop = 0;
if(reverse)
{
start = something.size();
stop = 0;
}
foreach(i in range(start, stop))
{
// do step 2
if (isSomeValue)
{
// do step 3
}
else
{
if(doElse)
break;
}
}
// do step 4
}
}它的可读性较低,但不会复制粘贴代码。
发布于 2016-03-22 14:17:36
有时候重复自己是个好主意。或者有时候它并不是在重复你自己。
在这里,您的控制流似乎不同,但是注释中的不同步骤是相同的。如果是这样的话,那么最好的选择是编写可重用的函数,这些函数可以自己处理步骤,可以在任何需要的地方调用,然后围绕它们构建不同的控制流结构。
您可以构建一些精心设计的对象或模板来为您执行控制流,但您必须想知道其中的要点。您不需要在执行过程中更改控制流,也不需要使其可插拔,因此以一种很好的、显式的方式对控制流进行编码,并在代码真正相同的地方使用Step1() Step2()等。
https://softwareengineering.stackexchange.com/questions/313484
复制相似问题