加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 1 工廠方法模式
    • 2 實(shí)例
    • 總結(jié)
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

《大話設(shè)計(jì)模式》解讀05-工廠方法

08/20 10:10
720
閱讀需 14 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

上篇文章,介紹了《大話設(shè)計(jì)模式》的第7章——代理模式。

本篇,來(lái)介紹《大話設(shè)計(jì)模式》的第8章——工廠方法模式。并通過(guò)C++代碼實(shí)現(xiàn)實(shí)例代碼的功能。

1 工廠方法模式

工廠方法模式(Factory Method):定義了一個(gè)創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類。

工廠方法使一個(gè)類的實(shí)例化延遲到了子類。

工廠方法模式的類圖如下:

    Product:產(chǎn)品類,定義工廠方法所建立的對(duì)象的接口ConcreateProduct:具體產(chǎn)品類,實(shí)現(xiàn)了產(chǎn)品類的接口Creater:創(chuàng)造者類,聲明工廠方法,返回一個(gè)產(chǎn)品類的對(duì)象ConcreateCreater:具體創(chuàng)造者類,重新定義工廠方法,來(lái)返回一個(gè)具體產(chǎn)品

2 實(shí)例

背景:書中小故事,小菜的同班同學(xué)薛磊風(fēng),一直學(xué)雷鋒做好事幫助一個(gè)老人,但最近被車撞住院了,就委托其他同學(xué)繼續(xù)幫他做好事??梢允嵌鄠€(gè)同學(xué)都去,例如學(xué)雷鋒的大學(xué)1、學(xué)雷鋒的大學(xué)2、學(xué)雷鋒的大學(xué)n,當(dāng)然也可以是志愿者去。

題目:用代碼的形式來(lái)實(shí)現(xiàn)學(xué)雷鋒做好事

2.1 版本一:類繼承

版本一的實(shí)現(xiàn)比較簡(jiǎn)單,僅使用類繼續(xù)的思想,讓學(xué)雷鋒的大學(xué)生,繼承雷鋒做好事的具體事項(xiàng)即可。

2.1.1 雷鋒類與大學(xué)生類

這里需要實(shí)現(xiàn)兩個(gè)類:

雷鋒類:定義一下做好事的具體方法,掃地、洗衣、買米

大學(xué)生類:直接繼承雷鋒類即可

// 雷鋒
class LeiFeng
{
public:
    void Sweep()
    {
        printf("掃地n");
    }
    
    void Wash()
    {
        printf("洗衣n");
    }    
    
    void BuyRice()
    {
        printf("買米n");
    }  
};

// 學(xué)雷鋒的大學(xué)生
class Undergraduate : LeiFeng
{
};

2.1.2 主函數(shù)

假設(shè)有3個(gè)學(xué)生在學(xué)雷鋒做好事。

首先,實(shí)例化三個(gè)學(xué)雷鋒的大學(xué)生,這里通過(guò)new是形式,返回在指針轉(zhuǎn)為(LeiFeng *)類型。

然后,就可以調(diào)用雷鋒做好事的方法來(lái)做好事了。

int main()
{
    // 實(shí)例化三個(gè)學(xué)雷鋒的大學(xué)生
    LeiFeng *student1 = (LeiFeng *)(new Undergraduate());
    LeiFeng *student2 = (LeiFeng *)(new Undergraduate());
    LeiFeng *student3 = (LeiFeng *)(new Undergraduate());
    // 學(xué)雷鋒做好事
    student1->Sweep();
    student2->Wash();
    student3->BuyRice();
    
    delete student1;
    delete student2;
    delete student3;
    
    return 0;
}

代碼運(yùn)行效果如下:

版本一中,僅實(shí)現(xiàn)了大學(xué)生學(xué)雷鋒做好事,如果社區(qū)志愿者也要學(xué)雷鋒做好事,就要?jiǎng)?chuàng)建志愿者類了,并且學(xué)雷鋒做好事,不需要知道具體是誰(shuí)在做好事,因此可以使用簡(jiǎn)單工廠來(lái)實(shí)例化具體要做好事的人,下面來(lái)看版本二。

2.2 版本二:簡(jiǎn)單工廠模式

版本二,類圖如下:

    學(xué)雷鋒的大學(xué)生類和學(xué)雷鋒的志愿者類來(lái)繼承雷鋒類簡(jiǎn)單工廠類依賴于雷鋒類,簡(jiǎn)單工廠的作用是實(shí)例化具體學(xué)雷鋒做好事的人

2.2.1 雷鋒類、學(xué)雷鋒類與簡(jiǎn)單工廠類

這里需要實(shí)現(xiàn)兩個(gè)類:

    雷鋒類(同版本一)學(xué)雷鋒的大學(xué)生類(同版本一)學(xué)雷鋒的志愿者類:直接繼承雷鋒類即可簡(jiǎn)單雷鋒工廠類:根據(jù)參數(shù)類型來(lái)決定是實(shí)例化學(xué)雷鋒的大學(xué)生還是學(xué)雷雷鋒的志愿者
// 雷鋒
class LeiFeng
{
public:
    void Sweep()
    {
        printf("掃地n");
    }
    
    void Wash()
    {
        printf("洗衣n");
    }    
    
    void BuyRice()
    {
        printf("買米n");
    }  
};

// 學(xué)雷鋒的大學(xué)生
class Undergraduate : LeiFeng
{
};

// 學(xué)雷鋒的志愿者
class Volunteer : LeiFeng
{
};

// 學(xué)雷鋒的人物類型
enum XUELEIFENG_TYPE
{
    XLF_TYPE_STUDENT,
    XLF_TYPE_VOLUNTEER,
    XLF_TYPE_NUM,
};

// 簡(jiǎn)單雷鋒工廠
class SimpleFactory
{
public:
    LeiFeng *CreateLeiFeng(XUELEIFENG_TYPE type)
    {
        LeiFeng *result;
        switch(type)
        {
            case XLF_TYPE_STUDENT: // 學(xué)雷鋒的大學(xué)生
            {
                result = (LeiFeng *)(new Undergraduate());
                break;
            }
            case XLF_TYPE_VOLUNTEER: // 學(xué)雷鋒的志愿者
            {
                result = (LeiFeng *)(new Volunteer());
                break;
            }
            default:
                break;
        }
        
        return result;
    }
};

2.2.2 主函數(shù)

首先,實(shí)例化了一個(gè)簡(jiǎn)單雷鋒工廠。

然后,給簡(jiǎn)單工廠的CreateLeiFeng方法傳入學(xué)生參數(shù),得到學(xué)生對(duì)象,傳入志愿者參數(shù),得到志愿者對(duì)象。

最后,調(diào)用雷鋒做好事的方法來(lái)做好事了。

int main()
{
    // 簡(jiǎn)單雷鋒工廠
    SimpleFactory simpleFactory; 
    // 實(shí)例化兩個(gè)學(xué)雷鋒的大學(xué)生和一個(gè)學(xué)雷鋒的志愿者
    LeiFeng *student1   = simpleFactory.CreateLeiFeng(XLF_TYPE_STUDENT);   
    LeiFeng *student2   = simpleFactory.CreateLeiFeng(XLF_TYPE_STUDENT);   
    LeiFeng *volunteer1 = simpleFactory.CreateLeiFeng(XLF_TYPE_VOLUNTEER); 
    
    // 學(xué)雷鋒做好事
    student1->Sweep();
    student2->Wash();
    volunteer1->BuyRice();
    
    delete student1;
    delete student2;
    delete volunteer1;
    
    return 0;
}

代碼運(yùn)行效果如下:

版本二運(yùn)用了簡(jiǎn)單工廠方法,下面來(lái)看工廠方法是如何實(shí)現(xiàn)的。

2.3 版本三:工廠方法模式

版本三使用工廠方法模式,類圖如下:

    學(xué)雷鋒的大學(xué)生類和學(xué)雷鋒的志愿者類來(lái)繼承雷鋒類學(xué)雷鋒的大學(xué)生工廠類和學(xué)雷鋒的志愿者工廠類來(lái)繼承雷鋒工廠類

注意工廠方法與簡(jiǎn)單工廠的區(qū)分,工廠方法是與每一個(gè)產(chǎn)品對(duì)應(yīng)的,有幾個(gè)類型的產(chǎn)品,就有幾個(gè)類型的工廠。

工廠方法雖然看起來(lái)復(fù)雜了,但這種方式其實(shí)遵循的是開放-封閉原則,即如果要再新加一種學(xué)雷鋒的人物類型,同時(shí)再增加一個(gè)對(duì)應(yīng)的工廠方法類即可,不需要需要之前的代碼。而如果是使用簡(jiǎn)單工廠,就要修改簡(jiǎn)單工廠類了。

2.3.1 ?雷鋒類、學(xué)雷鋒類與學(xué)雷鋒的工廠方法類

這里需要實(shí)現(xiàn)六個(gè)類:

    雷鋒類(同版本一)學(xué)雷鋒的大學(xué)生類(同版本一)學(xué)雷鋒的志愿者類(同版本二)雷鋒工廠類:虛基類,提供一個(gè)創(chuàng)建學(xué)雷鋒的對(duì)象的接口學(xué)雷鋒的大學(xué)生工廠類:繼承雷鋒工廠類,返回的是學(xué)雷鋒的大學(xué)生對(duì)象學(xué)雷鋒的志愿者工廠類:繼承雷鋒工廠類,返回的是學(xué)雷鋒的志愿者對(duì)象
// 雷鋒
class LeiFeng
{
public:
    void Sweep()
    {
        printf("掃地n");
    }
    
    void Wash()
    {
        printf("洗衣n");
    }    
    
    void BuyRice()
    {
        printf("買米n");
    }  
};

// 雷鋒工廠
class IFactory
{
public:
    virtual LeiFeng *CreateLeiFeng()
    {
        return nullptr;
    }
};

// 學(xué)雷鋒的大學(xué)生
class Undergraduate : LeiFeng
{
};

// 學(xué)雷鋒的大學(xué)生工廠
class UndergraduateFactory : IFactory
{
public:
    LeiFeng *CreateLeiFeng()
    {
        return (LeiFeng *)(new Undergraduate());
    }
};

// 學(xué)雷鋒的志愿者
class Volunteer : LeiFeng
{
};

// 學(xué)雷鋒的志愿者工廠
class VolunteerFactory : IFactory
{
public:
    LeiFeng *CreateLeiFeng()
    {
        return (LeiFeng *)(new Volunteer());
    }
};

2.3.2 主函數(shù)

首先,實(shí)例化了一個(gè)學(xué)雷鋒的大學(xué)生工廠。

然后,通過(guò)學(xué)雷鋒的大學(xué)生工廠來(lái)實(shí)例化學(xué)雷鋒的大學(xué)生對(duì)象,并調(diào)用學(xué)雷鋒做好事的接口做好事即可。

最后,學(xué)雷鋒的志愿者的邏輯與學(xué)雷鋒的大學(xué)生類似。

int main()
{
    // 學(xué)雷鋒的大學(xué)生工廠
    IFactory *undergraduateFactory = (IFactory *)(new UndergraduateFactory());
    // 實(shí)例化兩個(gè)學(xué)雷鋒的大學(xué)
    LeiFeng *student1   = undergraduateFactory->CreateLeiFeng();
    LeiFeng *student2   = undergraduateFactory->CreateLeiFeng();
    // 學(xué)雷鋒做好事
    tudent1->Sweep();
    student2->Wash();
    
    delete student1;
    delete student2;
    delete undergraduateFactory;
    
    // 學(xué)雷鋒的志愿者工廠
    IFactory *volunteerFactory = (IFactory *)(new VolunteerFactory());
    // 實(shí)例化一個(gè)學(xué)雷鋒的志愿者
    LeiFeng *volunteer1 = volunteerFactory->CreateLeiFeng();
    // 學(xué)雷鋒做好事
    volunteer1->BuyRice();

    delete volunteer1;
    delete volunteerFactory;
    
    return 0;
}

代碼運(yùn)行效果如下:

總結(jié)

本篇介紹了設(shè)計(jì)模式中的工廠方法模式,并通過(guò)學(xué)雷鋒做好事的實(shí)例,使用C++編程,來(lái)演示工廠方法模式的使用。

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
XRCGB25M000F3A00R0 1 Murata Manufacturing Co Ltd Parallel - Fundamental Quartz Crystal, 25MHz Nom, ROHS AND REACH COMPLIANT, SMALL, SMD, 3 PIN

ECAD模型

下載ECAD模型
$0.34 查看
M25P05-AVMN6P 1 Rochester Electronics LLC 64KX8 FLASH 2.7V PROM, PDSO8, 0.150 INCH, ROHS COMPLIANT, PLASTIC, SOP-8
$0.79 查看
S29GL256P10FFI020 1 AMD Flash, 16MX16, 100ns, PBGA64,
$9.29 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

控制科學(xué)與工程碩士,日常分享單片機(jī)、嵌入式、C/C++、Linux等學(xué)習(xí)經(jīng)驗(yàn)干貨~