• 正文
    • 1 工廠方法模式
    • 2 實(shí)例
    • 總結(jié)
  • 推薦器件
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

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

2024/08/20
1024
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

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

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

1 工廠方法模式

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

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

工廠方法模式的類(lèi)圖如下:

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

2 實(shí)例

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

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

2.1 版本一:類(lèi)繼承

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

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

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

雷鋒類(lèi):定義一下做好事的具體方法,掃地、洗衣、買(mǎi)米

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

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

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

2.1.2 主函數(shù)

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

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

然后,就可以調(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)建志愿者類(lèi)了,并且學(xué)雷鋒做好事,不需要知道具體是誰(shuí)在做好事,因此可以使用簡(jiǎn)單工廠來(lái)實(shí)例化具體要做好事的人,下面來(lái)看版本二。

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

版本二,類(lèi)圖如下:

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

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

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

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

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

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

// 學(xué)雷鋒的人物類(lèi)型
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 版本三:工廠方法模式

版本三使用工廠方法模式,類(lèi)圖如下:

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

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

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

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

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

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

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à)格 更多信息
AT24C512C-SSHD-B 1 Atmel Corporation EEPROM, 64KX8, Serial, CMOS, PDSO8, 0.150 INCH, GREEN, PLASTIC, MS-012AA, SOIC-8

ECAD模型

下載ECAD模型
$1.22 查看
510JCA25M0000BAGR 1 Silicon Laboratories Inc LVDS Output Clock Oscillator,
暫無(wú)數(shù)據(jù) 查看
LTC6906HS6#TRMPBF 1 Linear Technology LTC6906 - Micropower, 10kHz to 1MHz Resistor Set Oscillator in SOT-23; Package: SOT; Pins: 6; Temperature Range: -40°C to 125°C
暫無(wú)數(shù)據(jù) 查看

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶(hù)資源
  • 寫(xiě)文章/發(fā)需求
立即登錄