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