首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板模式是实现DRY的好方法吗?

模板模式是实现DRY的好方法吗?
EN

Software Engineering用户
提问于 2016-03-22 13:39:44
回答 4查看 691关注 0票数 4

我的问题是:

我有这样的班级结构:

代码语言:javascript
复制
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
    }
};

正如您在Child2Child3中所看到的,与Child1不同的是,Child2循环从相反的方向发展,而在Child3中,也有elsebreak语句。我希望您同意,这些算法只是略有不同,我几乎代码复制。对于这种类似的结构,是否有更好的方法来避免在许多不同的地方编写类似的代码?

这里是我想使用的干原理,虽然我不做代码复制,但是只编写类似的代码。我只是在几个类中看到了类似的构造。使用巧妙的模板法模式能消除类似的代码吗?或者其他方法?

EN

回答 4

Software Engineering用户

回答已采纳

发布于 2016-03-22 15:57:37

我要开始重构共同的部分,而不是不同的部分:

代码语言:javascript
复制
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所指出的(请注意,这没有显示模板方法模式)。

但是,您必须考虑这是否确实改善了您的代码。扪心自问:如果你必须增加一些额外的特性,因为你在三种方法中有“相似的部分”,但只有一种,这是否真的有被遗忘的风险呢?或者是相反的事实:是否因为你把三种方法概括为一种,而现在你不能再单独地改变它们,就很难改变什么?如果你能回答这个问题,你就知道该怎么做。

票数 5
EN

Software Engineering用户

发布于 2016-03-22 14:31:24

像这样的怎么样?

代码语言:javascript
复制
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
}
}

它的可读性较低,但不会复制粘贴代码。

票数 3
EN

Software Engineering用户

发布于 2016-03-22 14:17:36

有时候重复自己是个好主意。或者有时候它并不是在重复你自己。

在这里,您的控制流似乎不同,但是注释中的不同步骤是相同的。如果是这样的话,那么最好的选择是编写可重用的函数,这些函数可以自己处理步骤,可以在任何需要的地方调用,然后围绕它们构建不同的控制流结构。

您可以构建一些精心设计的对象或模板来为您执行控制流,但您必须想知道其中的要点。您不需要在执行过程中更改控制流,也不需要使其可插拔,因此以一种很好的、显式的方式对控制流进行编码,并在代码真正相同的地方使用Step1() Step2()等。

票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/313484

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档