上篇文章,介紹了《大話設(shè)計模式》的第7章——代理模式。
本篇,來介紹《大話設(shè)計模式》的第8章——工廠方法模式。并通過C++代碼實現(xiàn)實例代碼的功能。
1 工廠方法模式
工廠方法模式(Factory Method):定義了一個創(chuàng)建對象的接口,讓子類決定實例化哪一個類。
工廠方法使一個類的實例化延遲到了子類。
工廠方法模式的類圖如下:
- Product:產(chǎn)品類,定義工廠方法所建立的對象的接口ConcreateProduct:具體產(chǎn)品類,實現(xiàn)了產(chǎn)品類的接口Creater:創(chuàng)造者類,聲明工廠方法,返回一個產(chǎn)品類的對象ConcreateCreater:具體創(chuàng)造者類,重新定義工廠方法,來返回一個具體產(chǎn)品
2 實例
背景:書中小故事,小菜的同班同學薛磊風,一直學雷鋒做好事幫助一個老人,但最近被車撞住院了,就委托其他同學繼續(xù)幫他做好事。可以是多個同學都去,例如學雷鋒的大學1、學雷鋒的大學2、學雷鋒的大學n,當然也可以是志愿者去。
題目:用代碼的形式來實現(xiàn)學雷鋒做好事
2.1 版本一:類繼承
版本一的實現(xiàn)比較簡單,僅使用類繼續(xù)的思想,讓學雷鋒的大學生,繼承雷鋒做好事的具體事項即可。
2.1.1 雷鋒類與大學生類
這里需要實現(xiàn)兩個類:
雷鋒類:定義一下做好事的具體方法,掃地、洗衣、買米
大學生類:直接繼承雷鋒類即可
// 雷鋒
class LeiFeng
{
public:
void Sweep()
{
printf("掃地n");
}
void Wash()
{
printf("洗衣n");
}
void BuyRice()
{
printf("買米n");
}
};
// 學雷鋒的大學生
class Undergraduate : LeiFeng
{
};
2.1.2 主函數(shù)
假設(shè)有3個學生在學雷鋒做好事。
首先,實例化三個學雷鋒的大學生,這里通過new是形式,返回在指針轉(zhuǎn)為(LeiFeng *)類型。
然后,就可以調(diào)用雷鋒做好事的方法來做好事了。
int main()
{
// 實例化三個學雷鋒的大學生
LeiFeng *student1 = (LeiFeng *)(new Undergraduate());
LeiFeng *student2 = (LeiFeng *)(new Undergraduate());
LeiFeng *student3 = (LeiFeng *)(new Undergraduate());
// 學雷鋒做好事
student1->Sweep();
student2->Wash();
student3->BuyRice();
delete student1;
delete student2;
delete student3;
return 0;
}
代碼運行效果如下:
版本一中,僅實現(xiàn)了大學生學雷鋒做好事,如果社區(qū)志愿者也要學雷鋒做好事,就要創(chuàng)建志愿者類了,并且學雷鋒做好事,不需要知道具體是誰在做好事,因此可以使用簡單工廠來實例化具體要做好事的人,下面來看版本二。
2.2 版本二:簡單工廠模式
版本二,類圖如下:
- 學雷鋒的大學生類和學雷鋒的志愿者類來繼承雷鋒類簡單工廠類依賴于雷鋒類,簡單工廠的作用是實例化具體學雷鋒做好事的人
2.2.1 雷鋒類、學雷鋒類與簡單工廠類
這里需要實現(xiàn)兩個類:
- 雷鋒類(同版本一)學雷鋒的大學生類(同版本一)學雷鋒的志愿者類:直接繼承雷鋒類即可簡單雷鋒工廠類:根據(jù)參數(shù)類型來決定是實例化學雷鋒的大學生還是學雷雷鋒的志愿者
// 雷鋒
class LeiFeng
{
public:
void Sweep()
{
printf("掃地n");
}
void Wash()
{
printf("洗衣n");
}
void BuyRice()
{
printf("買米n");
}
};
// 學雷鋒的大學生
class Undergraduate : LeiFeng
{
};
// 學雷鋒的志愿者
class Volunteer : LeiFeng
{
};
// 學雷鋒的人物類型
enum XUELEIFENG_TYPE
{
XLF_TYPE_STUDENT,
XLF_TYPE_VOLUNTEER,
XLF_TYPE_NUM,
};
// 簡單雷鋒工廠
class SimpleFactory
{
public:
LeiFeng *CreateLeiFeng(XUELEIFENG_TYPE type)
{
LeiFeng *result;
switch(type)
{
case XLF_TYPE_STUDENT: // 學雷鋒的大學生
{
result = (LeiFeng *)(new Undergraduate());
break;
}
case XLF_TYPE_VOLUNTEER: // 學雷鋒的志愿者
{
result = (LeiFeng *)(new Volunteer());
break;
}
default:
break;
}
return result;
}
};
2.2.2 主函數(shù)
首先,實例化了一個簡單雷鋒工廠。
然后,給簡單工廠的CreateLeiFeng方法傳入學生參數(shù),得到學生對象,傳入志愿者參數(shù),得到志愿者對象。
最后,調(diào)用雷鋒做好事的方法來做好事了。
int main()
{
// 簡單雷鋒工廠
SimpleFactory simpleFactory;
// 實例化兩個學雷鋒的大學生和一個學雷鋒的志愿者
LeiFeng *student1 = simpleFactory.CreateLeiFeng(XLF_TYPE_STUDENT);
LeiFeng *student2 = simpleFactory.CreateLeiFeng(XLF_TYPE_STUDENT);
LeiFeng *volunteer1 = simpleFactory.CreateLeiFeng(XLF_TYPE_VOLUNTEER);
// 學雷鋒做好事
student1->Sweep();
student2->Wash();
volunteer1->BuyRice();
delete student1;
delete student2;
delete volunteer1;
return 0;
}
代碼運行效果如下:
版本二運用了簡單工廠方法,下面來看工廠方法是如何實現(xiàn)的。
2.3 版本三:工廠方法模式
版本三使用工廠方法模式,類圖如下:
- 學雷鋒的大學生類和學雷鋒的志愿者類來繼承雷鋒類學雷鋒的大學生工廠類和學雷鋒的志愿者工廠類來繼承雷鋒工廠類
注意工廠方法與簡單工廠的區(qū)分,工廠方法是與每一個產(chǎn)品對應(yīng)的,有幾個類型的產(chǎn)品,就有幾個類型的工廠。
工廠方法雖然看起來復(fù)雜了,但這種方式其實遵循的是開放-封閉原則,即如果要再新加一種學雷鋒的人物類型,同時再增加一個對應(yīng)的工廠方法類即可,不需要需要之前的代碼。而如果是使用簡單工廠,就要修改簡單工廠類了。
2.3.1 ?雷鋒類、學雷鋒類與學雷鋒的工廠方法類
這里需要實現(xiàn)六個類:
- 雷鋒類(同版本一)學雷鋒的大學生類(同版本一)學雷鋒的志愿者類(同版本二)雷鋒工廠類:虛基類,提供一個創(chuàng)建學雷鋒的對象的接口學雷鋒的大學生工廠類:繼承雷鋒工廠類,返回的是學雷鋒的大學生對象學雷鋒的志愿者工廠類:繼承雷鋒工廠類,返回的是學雷鋒的志愿者對象
// 雷鋒
class LeiFeng
{
public:
void Sweep()
{
printf("掃地n");
}
void Wash()
{
printf("洗衣n");
}
void BuyRice()
{
printf("買米n");
}
};
// 雷鋒工廠
class IFactory
{
public:
virtual LeiFeng *CreateLeiFeng()
{
return nullptr;
}
};
// 學雷鋒的大學生
class Undergraduate : LeiFeng
{
};
// 學雷鋒的大學生工廠
class UndergraduateFactory : IFactory
{
public:
LeiFeng *CreateLeiFeng()
{
return (LeiFeng *)(new Undergraduate());
}
};
// 學雷鋒的志愿者
class Volunteer : LeiFeng
{
};
// 學雷鋒的志愿者工廠
class VolunteerFactory : IFactory
{
public:
LeiFeng *CreateLeiFeng()
{
return (LeiFeng *)(new Volunteer());
}
};
2.3.2 主函數(shù)
首先,實例化了一個學雷鋒的大學生工廠。
然后,通過學雷鋒的大學生工廠來實例化學雷鋒的大學生對象,并調(diào)用學雷鋒做好事的接口做好事即可。
最后,學雷鋒的志愿者的邏輯與學雷鋒的大學生類似。
int main()
{
// 學雷鋒的大學生工廠
IFactory *undergraduateFactory = (IFactory *)(new UndergraduateFactory());
// 實例化兩個學雷鋒的大學
LeiFeng *student1 = undergraduateFactory->CreateLeiFeng();
LeiFeng *student2 = undergraduateFactory->CreateLeiFeng();
// 學雷鋒做好事
tudent1->Sweep();
student2->Wash();
delete student1;
delete student2;
delete undergraduateFactory;
// 學雷鋒的志愿者工廠
IFactory *volunteerFactory = (IFactory *)(new VolunteerFactory());
// 實例化一個學雷鋒的志愿者
LeiFeng *volunteer1 = volunteerFactory->CreateLeiFeng();
// 學雷鋒做好事
volunteer1->BuyRice();
delete volunteer1;
delete volunteerFactory;
return 0;
}
代碼運行效果如下:
總結(jié)
本篇介紹了設(shè)計模式中的工廠方法模式,并通過學雷鋒做好事的實例,使用C++編程,來演示工廠方法模式的使用。