【无标题】

前言

在遇到重复代码比较多时,使用继承来将重复的代码集中到父类中,子类只需要完成自己的逻辑,是一个不错的方法。

模板模式

模板模式可以概括为:当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模板的方法模式来处理。

例如,我们写一个做试卷的类,根据不同的考题做出作出不同的答案。

#include "Include.h"


class TestPaper1{
public:
    void Question1(){
        printf("倚天屠龙剑的玄铁可能是:\n");
        printf("a. 球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维\n");
        printf("答案:b\n");
    }
    void Question2(){
        printf("杨过,程英,陆无双铲除了情花,造成:\n");
        printf("a. 使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化\n");
        printf("答案:a\n");
    }
};


class TestPaper2{
public:
    void Question1(){
        printf("倚天屠龙剑的玄铁可能是:\n");
        printf("a. 球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维\n");
        printf("答案:d\n");
    }
    void Question2(){
        printf("杨过,程英,陆无双铲除了情花,造成:\n");
        printf("a. 使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化\n");
        printf("答案:b\n");
    }
};

void test1(){
    TestPaper1 p1;
    p1.Question1();
    p1.Question2();
    TestPaper2 p2;
    p2.Question1();
    p2.Question2();

}

int main(int argc, char** argv)
{
    test1();
    return 0;
}

控制台输出:

倚天屠龙剑的玄铁可能是:
a. 球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维
答案:b
杨过,程英,陆无双铲除了情花,造成:
a. 使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化
答案:a
倚天屠龙剑的玄铁可能是:
a. 球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维
答案:d
杨过,程英,陆无双铲除了情花,造成:
a. 使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化
答案:b

这种没有任何泛化的代码,重复的部分特别多,后期维护起来也很费力,如果需要增删一个问题活着修改一个问题,都需要做两次同样的操作,效率低下,所以应该将重复部分整合到父类中,子类只需要继承就可以了。修改代码如下:

class TestPaper{
public:
    void Question1(){
        printf("倚天屠龙剑的玄铁可能是:\n");
        printf("a. 球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维\n");
    }
    void Question2(){
        printf("杨过,程英,陆无双铲除了情花,造成:\n");
        printf("a. 使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化\n");
    }
};

class TestPaperA: public TestPaper {
public:
    void testQuestion1(){
        Question1();
        printf("答案:b\n");
    }

    void testQuestion2(){
        Question2();
        printf("答案:a\n");
    }
};

class TestPaperB: public TestPaper {
public:
    void testQuestion1(){
        Question1();
        printf("答案:d\n");
    }

    void testQuestion2(){
        Question2();
        printf("答案:b\n");
    }
};
void test2(){
    TestPaperA pA;
    pA.testQuestion1();
    pA.testQuestion2();
    TestPaperB pB;
    pB.testQuestion1();
    pB.testQuestion2();
}

int main(int argc, char** argv)
{
    test2();
    return 0;
}

控制台输出的内容相同。

修改以后的代码,将题目部分放到了父类中,子类只需要调用父类的方法然后在子类中给出自己的答案即可,但是这代码还是有重复的地方,就是调用父类的问题这个过程,每个子类还是都做了一遍,所以这部分代码也可以放到父类中去,那子类如果给出自己的答案呢,这里我们可以使用虚方法,子类实现父类给出的作答接口,父类调用这个虚函数即可。

class TestPaperAbstract{
public:
    void Question1(){
        printf("倚天屠龙剑的玄铁可能是:\n");
        printf("a. 球墨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维\n");
        Answer1();
    }
    void Question2(){
        printf("杨过,程英,陆无双铲除了情花,造成:\n");
        printf("a. 使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化\n");
        Answer2();
    }

    virtual void Answer1() = 0;
    virtual void Answer2() = 0;
};


class TestPaperAA: public TestPaperAbstract {
public:
    virtual void Answer1() override{
        printf("答案:b\n");
    }

    virtual void Answer2() override{
        printf("答案:a\n");
    }
};

class TestPaperBB: public TestPaperAbstract {
public:
    virtual void Answer1() override{
        printf("答案:d\n");
    }

    virtual void Answer2() override{
        printf("答案:b\n");
    }
};

void test3(){
    TestPaperAA pAA;
    pAA.Question1();
    pAA.Question2();
    TestPaperBB pBB;
    pBB.Question1();
    pBB.Question2();
}

int main(int argc, char** argv)
{
    test3();
    return 0;
}

子类重写Answer1/Answer2虚方法,将自己的答案填上,就实现了和第一份代码相同的功能,将父类的某一方法的实现延迟到子类中,利用了多态性实现了代码复用。

总结

模板方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势。模板方法模式提供了一个很好的代码复用平台。

当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。

总结起来一句话就是,模板模式提取类库中的公共行为到抽象类中。

你可能感兴趣的:(设计模式,chrome,算法,前端)