模版方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,模版方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
本文使用书中考试答卷的例子,代码使用C++语言描述,代码存在的不足或问题有望各位指出。
(1)模版方法模式代码框架
//模版方法模式
#include <iostream>
using namespace std;
class AbstractClass
{
public:
AbstractClass(){}
virtual ~AbstractClass(){}
virtual void primitiveOperation1()=0; //一些抽象行为放到子类去实现
virtual void primitiveOperation2()=0;
void templateMethod() //模版方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,
{ //它们都推迟到子类实现
primitiveOperation1();
primitiveOperation2();
cout<< " "<<endl;
}
};
class ConcreteClassA : public AbstractClass
{
public:
void primitiveOperation1() override
{
cout <<"具体类A方法1实现" << endl;
}
void primitiveOperation2() override
{
cout << "具体类A方法2实现" << endl;
}
};
class ConcreteClassB : public AbstractClass
{
public:
void primitiveOperation1() override
{
cout << "具体类B方法1实现" <<endl;
}
void primitiveOperation2() override
{
cout << "具体类B方法2实现" <<endl;
}
};
int main()
{
AbstractClass *c;
c = new ConcreteClassA();
c->templateMethod();
c = new ConcreteClassB();
c->templateMethod();
delete c;
return 0;
}
1、AbstractClass 是抽象类,其实也就是一抽象模版,定义并实现了一个模版方法。这个模版方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
2、ConcreteClass,实现父类所定义的一个或多个抽象方法。每一个AbstractClass 都可以有任意多个ConcreteClass与之对应,而每一个ConcreteClass都可以给出这些抽象方法的不同实现,从而使得顶级逻辑的实现各不相同。
(2)考试答卷事例不使用模版方法实现如下:
//模版方法模式
#include <iostream>
using namespace std;
//试卷父类
class TestPaper
{
public:
void testQuestion1()
{
cout<< "1+1=() a.1 b.2 c.3 d.4" <<endl;
}
void testQuestion2()
{
cout << "2+2=() a.1 b.2 c.3 d.4" <<endl;
}
void testQuestion3()
{
cout << "3+3=() a.3 b.4 c.6 d.5" <<endl;
}
};
class TestPaperA : public TestPaper
{
public:
void testQuestion1()
{
TestPaper::testQuestion1();
cout<< "答案:b"<<endl;
}
void testQuestion2()
{
TestPaper::testQuestion2();
cout<< "答案:d"<<endl;
}
void testQuestion3()
{
TestPaper::testQuestion3();
cout<<"答案:c"<<endl;
}
};
class TestPaperB : public TestPaper
{
public:
void testQuestion1()
{
TestPaper::testQuestion1();
cout<< "答案:b"<<endl;
}
void testQuestion2()
{
TestPaper::testQuestion2();
cout<< "答案:d"<<endl;
}
void testQuestion3()
{
TestPaper::testQuestion3();
cout<<"答案:d"<<endl;
}
};
int main()
{
cout <<"学生A抄的试卷:"<< endl;
TestPaperA studentA;
studentA.testQuestion1();
studentA.testQuestion2();
studentA.testQuestion3();
cout << "学生B抄的试卷:" << endl;
TestPaperB studentB;
studentB.testQuestion1();
studentB.testQuestion2();
studentB.testQuestion3();
return 0;
}
(3)考试答卷事例使用模版方法实现:
//使用模版方法模式实现
#include <iostream>
using namespace std;
//试卷父类
class TestPaper
{
public:
TestPaper(){}
virtual ~TestPaper(){}
void testQuestion1()
{
cout<< "1+1=() a.1 b.2 c.3 d.4" <<endl;
cout << Answer1() <<endl;
}
void testQuestion2()
{
cout << "2+2=() a.1 b.2 c.3 d.4" <<endl;
cout << Answer2() <<endl;
}
void testQuestion3()
{
cout << "3+3=() a.3 b.4 c.6 d.5" <<endl;
cout << Answer2() <<endl;
}
protected:
virtual string Answer1()
{
return "";
}
virtual string Answer2()
{
return "";
}
virtual string Answer3()
{
return "";
}
};
class TestPaperA : public TestPaper
{
protected:
string Answer1() override
{
return "b";
}
string Answer2() override
{
return "c";
}
string Answer3() override
{
return "d";
}
};
class TestPaperB : public TestPaper
{
protected:
string Answer1() override
{
return "b";
}
string Answer2() override
{
return "d";
}
string Answer3() override
{
return "d";
}
};
int main()
{
cout <<"学生A抄的试卷:"<< endl;
TestPaper *studentA = new TestPaperA(); //将子类变量的声明改成了父类,利用了多态性
studentA->testQuestion1(); // 实现了代码的复用
studentA->testQuestion2();
studentA->testQuestion3();
cout << "学生B抄的试卷:" << endl;
TestPaper *studentB = new TestPaperA();
studentB->testQuestion1();
studentB->testQuestion2();
studentB->testQuestion3();
delete studentA;
delete studentB;
return 0;
}
模版方法模式特点
1、模版方法模式是通过把不变行为搬到超类,去除子类中的重复代码来体现它的优势。
2、模版方法模式就是提供了一个很好多的代码复用平台。
3、当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模版方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。