上篇文章,介紹了《大話設(shè)計模式》的第9章——原型模式。
本篇,來介紹《大話設(shè)計模式》的第10章——模板方法。并通過C++代碼實現(xiàn)實例代碼的功能。
1 模板方法
模板方法模式(TemplateMethod):定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
2 實例
背景:書中小故事,抄題目做題,看不清黑板,題目抄錯,導致做題肯定是錯的。
題目:用代碼的形式來實現(xiàn)。
2.1 版本一:單獨的試卷類
版本一的實現(xiàn)比較簡單,學生甲和學生乙單獨抄試卷做題,分別實現(xiàn)兩個類。
2.1.1 兩個同學分別抄題目作答
定義兩個類,實現(xiàn)兩個同學獨自抄題做題:
// 學生甲抄的試卷
class TestPaperA
{
public:
// 試題1
void TestQuestion1()
{
printf("1.在TCP/IP協(xié)議棧中,應用層協(xié)議數(shù)據(jù)單元為(). A.消息 B.段 C.用戶數(shù)據(jù)報 D.幀n");
printf("答案: Bn");
}
// 試題2
void TestQuestion2()
{
printf("2.在C語言中,char型數(shù)據(jù)在內(nèi)存中的存儲形式是(). A.補碼 B.反碼 C.原碼 D.ASCII碼n");
printf("答案: Dn");
}
// 試題3
void TestQuestion3()
{
printf("3.某計算機字長是32位,存儲容量是256KB, 按字編址的尋址范圍是(). A.128K B.64K C.32K D.16Kn");
printf("答案: Bn");
}
};
// 學生乙抄的試卷
class TestPaperB
{
public:
// 試題1
void TestQuestion1()
{
printf("1.在TCP/IP協(xié)議棧中,應用層協(xié)議數(shù)據(jù)單元為(). A.消息 B.段 C.用戶數(shù)據(jù)報 D.幀n");
printf("答案: Bn");
}
// 試題2
void TestQuestion2()
{
printf("2.在C語言中,char型數(shù)據(jù)在內(nèi)存中的存儲形式是(). A.補碼 B.反碼 C.原碼 D.ASCII碼n");
printf("答案: Bn");
}
// 試題3
void TestQuestion3()
{
printf("3.某計算機字長是32位,存儲容量是256KB, 按字編址的尋址范圍是(). A.128K B.64K C.32K D.16Kn");
printf("答案: Cn");
}
};
2.1.2 主函數(shù)
首先,實例化兩個同學,抄題做題,
然后,就可以調(diào)用展示接口來顯示出來了。
int main()
{
printf("學生甲抄的試卷:n");
TestPaperA studentA;
studentA.TestQuestion1();
studentA.TestQuestion2();
studentA.TestQuestion3();
printf("n學生乙抄的試卷:n");
TestPaperB studentB;
studentB.TestQuestion1();
studentB.TestQuestion2();
studentB.TestQuestion3();
return 0;
}
代碼運行效果如下:
下面來看版本二。
2.2 版本二:對試卷題目封裝為一個類
版本二,是將題目封裝為一個類,這樣就確保兩個同學做的題目是一樣的:
2.2.1 試題類
// 計算機試題
class TestPaper
{
public:
// 試題1
void TestQuestion1()
{
printf("1.在TCP/IP協(xié)議棧中,應用層協(xié)議數(shù)據(jù)單元為(). A.消息 B.段 C.用戶數(shù)據(jù)報 D.幀n");
}
// 試題2
void TestQuestion2()
{
printf("2.在C語言中,char型數(shù)據(jù)在內(nèi)存中的存儲形式是(). A.補碼 B.反碼 C.原碼 D.ASCII碼n");
}
// 試題3
void TestQuestion3()
{
printf("3.某計算機字長是32位,存儲容量是256KB, 按字編址的尋址范圍是(). A.128K B.64K C.32K D.16Kn");
}
};
2.2.2 ?兩個同學分別作答
定義的兩個同學類,繼承題目類,然后僅根據(jù)題目作答即可。
// 學生甲抄的試卷
class TestPaperA : public TestPaper
{
public:
// 試題1
void TestQuestion1()
{
TestPaper::TestQuestion1();
printf("答案: Bn");
}
// 試題2
void TestQuestion2()
{
TestPaper::TestQuestion2();
printf("答案: Dn");
}
// 試題3
void TestQuestion3()
{
TestPaper::TestQuestion3();
printf("答案: Bn");
}
};
// 學生乙抄的試卷
class TestPaperB : public TestPaper
{
public:
// 試題1
void TestQuestion1()
{
TestPaper::TestQuestion1();
printf("答案: Bn");
}
// 試題2
void TestQuestion2()
{
TestPaper::TestQuestion2();
printf("答案: Bn");
}
// 試題3
void TestQuestion3()
{
TestPaper::TestQuestion3();
printf("答案: Cn");
}
};
2.2.3 主函數(shù)
主函數(shù)不用改。
代碼運行效果如下:
2.3 版本三:模板方法模式
版本三,模板方法模式。在版本二中,每個同學的類中,還需要有重復的printf("答案: Xn");這類代碼,實際上,每個同學作答不一樣的地方,只是ABCD的這4個選項。
因此,可以將重復的printf也提升到試卷類中,并對ABCD的這4個選項的選擇提供一個虛方法,在運行時由子類(同學類)來實現(xiàn):
2.3.1 試題類
// 計算機試題
class TestPaper
{
public:
// 試題1
void TestQuestion1()
{
printf("1.在TCP/IP協(xié)議棧中,應用層協(xié)議數(shù)據(jù)單元為(). A.消息 B.段 C.用戶數(shù)據(jù)報 D.幀n");
printf("答案: %sn", Answer1().c_str());
}
// 試題2
void TestQuestion2()
{
printf("2.在C語言中,char型數(shù)據(jù)在內(nèi)存中的存儲形式是(). A.補碼 B.反碼 C.原碼 D.ASCII碼n");
printf("答案: %sn", Answer2().c_str());
}
// 試題3
void TestQuestion3()
{
printf("3.某計算機字長是32位,存儲容量是256KB, 按字編址的尋址范圍是(). A.128K B.64K C.32K D.16Kn");
printf("答案: %sn", Answer3().c_str());
}
protected:
virtual std::string Answer1() {return "";};
virtual std::string Answer2() {return "";};
virtual std::string Answer3() {return "";};
};
2.3.2 ?兩個同學分別作答
// 學生甲抄的試卷
class TestPaperA : public TestPaper
{
protected:
// 試題1
std::string Answer1() {return "B";};
// 試題2
std::string Answer2() {return "D";};
// 試題3
std::string Answer3() {return "B";};
};
// 學生乙抄的試卷
class TestPaperB : public TestPaper
{
protected:
// 試題1
std::string Answer1() {return "B";};
// 試題2
std::string Answer2() {return "B";};
// 試題3
std::string Answer3() {return "C";};
};
2.3.3 主函數(shù)
主函數(shù)不用改。
代碼運行效果如下:
總結(jié)
本篇介紹了設(shè)計模式中的模板方法模式,并通過學生抄寫題目作答的實例,使用C++編程,來演示模板方法模式的使用。
文章推薦