国产久操视频-国产久草视频-国产久热精品-国产久热香蕉在线观看-青青青青娱乐-青青青青在线成人视99

  • 正文
    • 1 面向?qū)ο缶幊?/span>
    • 2 計(jì)算器實(shí)例
    • 3 總結(jié)
  • 推薦器件
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

《大話設(shè)計(jì)模式》解讀01-簡(jiǎn)單工廠模式

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

本系列的文章,來介紹編程中的設(shè)計(jì)模式,介紹的內(nèi)容主要為《大話設(shè)計(jì)模式》的讀書筆記,并改用C++語言來實(shí)現(xiàn)(書中使用的是.NET中的C#),本篇來學(xué)習(xí)第一章,介紹的設(shè)計(jì)模式是——簡(jiǎn)單工廠模式。

1 面向?qū)ο缶幊?/h2>

設(shè)計(jì)模式依賴與面向?qū)ο缶幊堂懿豢煞?,因此在開始學(xué)習(xí)設(shè)計(jì)模式之前,先簡(jiǎn)單介紹下面向?qū)ο缶幊獭?/p>

先來看一個(gè)小故事:

話說三國(guó)時(shí)期,曹操在赤壁帶領(lǐng)百萬大軍,眼看就要滅掉東吳,統(tǒng)一天下,非常高性,于是大宴文武。

在酒席間,不覺吟到:“喝酒唱歌,人生真爽,......”,眾文武齊呼:“丞相好詩(shī)!”,

于是一臣子速速命令印刷工匠進(jìn)行刻版印刷,以便流傳天下。

印刷工匠刻好樣張,拿出來給曹操一看,曹操感覺不妥,

說道:“喝與唱,此話過俗,應(yīng)該改為對(duì)酒當(dāng)歌較好!”,

于是臣子就命令工匠重新來過,工匠眼看連夜刻版之功,徹底白費(fèi),心中叫苦不迭,只得照辦。

印刷工匠再次刻好樣張,拿出來給曹操過目,曹操細(xì)細(xì)一品,覺得還是不好,

說:“人生真爽太過直接,應(yīng)該改為問句才夠意境,因此應(yīng)改為對(duì)酒當(dāng)歌,人生幾何”,

當(dāng)臣子再次轉(zhuǎn)告工匠之時(shí),工匠暈倒......

那,問題出在哪里呢?

大概是三國(guó)時(shí)期還沒有活字印刷術(shù)吧,所以要改字的時(shí)候,就必須整個(gè)刻板全部重新雕刻。

如果有了活字印刷術(shù),其實(shí)只需要更改四個(gè)字即可,其余工作都未白做。

我們聯(lián)想編程,從這個(gè)小故事中,來體會(huì)一下編程中的一些思想:

    可維護(hù):要改字,只需更改需要變動(dòng)的字即可可復(fù)用:這些字并不是只是這次有用,后續(xù)如果在其它印刷中需要用,可重復(fù)使用可擴(kuò)展:如果詩(shī)中需要加字,只需另外單獨(dú)刻字即可靈活性:字的排列可以橫排,也可以豎排

面向?qū)ο缶幊?,通過封裝、繼承和多態(tài),把程序的耦合度降低。

傳統(tǒng)印刷術(shù)的問題就在于把所有字都刻在同一個(gè)版面上的耦合度太高。

使用設(shè)計(jì)模式可以使程序更加靈活,容易修改,并易于復(fù)用。

2 計(jì)算器實(shí)例

下面以一個(gè)計(jì)算器的代碼實(shí)例,來體會(huì)封裝的思想,以及簡(jiǎn)單工廠模式的使用。

題目:設(shè)計(jì)一個(gè)計(jì)算器控制臺(tái)程序,輸入為兩個(gè)數(shù)和運(yùn)算符,輸出結(jié)果

功能比較簡(jiǎn)單,先來看第一個(gè)版本的實(shí)現(xiàn)。

2.1 版本一:面向過程

第一個(gè)版本采用面向過程的思想,從接收用戶輸入,到數(shù)據(jù)運(yùn)算,以及最后的輸出,都是按順序在一個(gè)代碼塊中實(shí)現(xiàn)的:

int main()
{
    float numA = 0;
    float numB = 0;
    float result = 0;
    char operate;
    bool bSuccess = true;
    
    printf("please input a num A:n");
    scanf("%f", &numA);
    printf("please input a operate(+ - * ):n");
    std::cin >> operate;
    printf("please input a num B:n");
    scanf("%f", &numB);
    
    switch(operate)
    {
        case '+':
        {
            result = numA + numB;
            break;
        }
        case '-':
        {
            result = numA - numB;
            break;
        }
        case '*':
        {
            result = numA * numB;
            break;
        }
        case '/':
        {
            if (numB == 0)
            {
                bSuccess = false;
                printf("divisor cannot be 0!n");
                break;
            }
            result = numA / numB;
            break;
        }
        default:
        {
            bSuccess = false;
            break;
        }
    }
    
    if (bSuccess)
    {
        printf("%f %c %f = %fn", numA, operate, numB, result);
    }
    else
    {
        printf("[%f %c %f] calc fail!n", numA, operate, numB);
    }
    
    return 0;
}

該程序的運(yùn)行效果如下圖所示:

上述代碼實(shí)現(xiàn)本身沒有什么問題,但是,如果現(xiàn)在要再實(shí)現(xiàn)一個(gè)帶有UI界面的計(jì)算器,代碼能不能復(fù)用呢?很顯然不行,代碼都是在一起的。

因此,為了便于代碼復(fù)用,可以將計(jì)算部分的代碼和顯示部分的代碼分開,降低它們之間的耦合度。

2.2 版本二:對(duì)業(yè)務(wù)封裝

版本二則是對(duì)計(jì)算部分的業(yè)務(wù)代碼顯示部分的控制臺(tái)輸入輸出代碼分開。

計(jì)算部分的業(yè)務(wù)代碼,設(shè)計(jì)一個(gè)Operation運(yùn)算類,通過其成員函數(shù)GetResult來實(shí)現(xiàn)加減乘除運(yùn)算。

2.2.1 業(yè)務(wù)代碼

class Operation
{
public:
    bool GetResult(float numA, float numB, char operate, float &result)
    {
        bool bSuccess = true;
        
        switch(operate)
        {
            case '+':
            {
                result = numA + numB;
                break;
            }
            case '-':
            {
                result = numA - numB;
                break;
            }
            case '*':
            {
                result = numA * numB;
                break;
            }
            case '/':
            {
                if (numB == 0)
                {
                    bSuccess = false;
                    printf("divisor cannot be 0!n");
                    break;
                }
                result = numA / numB;
                break;
            }
            default:
            {
                bSuccess = false;
                break;
            }
        }
        
        return bSuccess;
    }
};

2.2.2 控制臺(tái)界面代碼

顯示部分的控制臺(tái)輸入輸出代碼,還在main函數(shù)中。

int main()
{
    float numA = 0;
    float numB = 0;
    float result = 0;
    char operate;
    
    printf("please input a num A:n");
    scanf("%f", &numA);
    printf("please input a operate(+ - * ):n");
    std::cin >> operate;
    printf("please input a num B:n");
    scanf("%f", &numB);
    
    Operation Op1;
    bool bSuccess = Op1.GetResult(numA, numB, operate, result);
    
    if (bSuccess)
    {
        printf("%f %c %f = %fn", numA, operate, numB, result);
    }
    else
    {
        printf("[%f %c %f] calc fail!n", numA, operate, numB);
    }
    
    return 0;
}

版本二的運(yùn)行效果演示如下:

上述的版本二的代碼實(shí)現(xiàn),就用到了面向?qū)ο笕筇匦灾械?strong>封裝。

那,上述代碼,是否可以做到靈活擴(kuò)展?

比如,如果希望增加一個(gè)開根號(hào)的運(yùn)算,如果改?

按照現(xiàn)有邏輯,需要修改Operation運(yùn)算類,在switch中增加一個(gè)分支。但這樣,會(huì)需要加減乘除的邏輯再次參與編譯,另外,如果在修改開根號(hào)的代碼時(shí),不小心改動(dòng)了加減乘除的邏輯,影響就大了。

因此,可以使用面向?qū)ο笾?strong>繼承和多態(tài)的思想,來實(shí)現(xiàn)各個(gè)運(yùn)算類的分離。

2.3 版本三:簡(jiǎn)單工廠

版本三用到了封裝、繼承、多態(tài),以及通過簡(jiǎn)單工廠來實(shí)例化出合適的對(duì)象。

2.3.1 Operation運(yùn)算類(父類)

Operation運(yùn)算類為一個(gè)抽象類,是加減乘除類的父類。

該類包含numA和numB兩個(gè)成員變量,以及一個(gè)虛函數(shù)GetResult用于計(jì)算運(yùn)算結(jié)果,各個(gè)子類中對(duì)其進(jìn)行具體的實(shí)現(xiàn)。

// 操作類(父類)
class Operation
{
public:
    float numA = 0;
    float numB = 0;
    
public:
    virtual float GetResult()
    {
        return 0;
    };
};

2.3.2 加減乘除類(子類)

加減乘除子類通過公有繼承Operation類,可以訪問其共有成員變量numA和numB,并對(duì)GetResult方法進(jìn)行具體的實(shí)現(xiàn):

// 加法類(子類)
class OperationAdd : public Operation
{
public:
    float GetResult()
    {
        return numA + numB;
    }
};

// 減法類(子類)
class OperationSub : public Operation
{
public:
    float GetResult()
    {
        return numA - numB;
    }
};

// 乘法類(子類)
class OperationMul : public Operation
{
public:
    float GetResult()
    {
        return numA * numB;
    }
};

// 除法類(子類)
class OperationDiv : public Operation
{
public:
    float GetResult()
    {
        if (numB == 0)
        {
            printf("divisor cannot be 0!n");
            return 0;
        }
        return numA / numB;
    }
};

2.3.3 簡(jiǎn)單運(yùn)算工廠類

為了能方便地實(shí)例化加減乘除類,考慮使用一個(gè)單獨(dú)的類來做這個(gè)創(chuàng)造實(shí)例的過程,這個(gè)就是工廠。

設(shè)計(jì)一個(gè)OperationFactory類來實(shí)現(xiàn),這樣,只要輸入運(yùn)算的符號(hào),就能實(shí)例化出合適的對(duì)象。

// 簡(jiǎn)單工廠模式
class OperationFactory
{
public:
    Operation *createOperation(char operation)
    {
        Operation *oper = nullptr;
        switch(operation)
        {
            case '+':
            {
                oper = (Operation *)(new OperationAdd());
                break;
            }
            case '-':
            {
                oper = (Operation *)(new OperationSub());
                break;
            }
            case '*':
            {
                oper = (Operation *)(new OperationMul());
                break;
            }
            case '/':
            {
                oper = (Operation *)(new OperationDiv());
                break;
            }
            default:
            {
                break;
            }
        }
        
        return oper;
    }
};

使用版本三,如果后續(xù)需要修改加法運(yùn)算,只需要修改OperationAdd類中的內(nèi)容即可,不會(huì)影響到其它計(jì)算類。

2.3.4 控制臺(tái)界面代碼

顯示部分的控制臺(tái)輸入輸出代碼,還在main函數(shù)中。

通過多態(tài),返回父類的方式,實(shí)現(xiàn)對(duì)應(yīng)運(yùn)算的計(jì)算結(jié)果。

{
    float numA = 0;
    float numB = 0;
    float result = 0;
    char operate;
    
    printf("please input a num A:n");
    scanf("%f", &numA);
    printf("please input a operate(+ - * ):n");
    std::cin >> operate;
    printf("please input a num B:n");
    scanf("%f", &numB);
    
    OperationFactory opFac;
    Operation *oper = nullptr;
    oper = opFac.createOperation(operate);
    if (oper != nullptr)
    {
        oper->numA = numA;
        oper->numB = numB;
        result = oper->GetResult();
        printf("%f %c %f = %fn", numA, operate, numB, result);
        
        delete oper;
    }
    else
    {
        printf("[%f %c %f] calc fail!n", numA, operate, numB);
    }
    
    return 0;
}

版本三的運(yùn)行效果演示如下:

版本三中,各個(gè)類之間的關(guān)系如下圖所示:

      • 運(yùn)算類是一個(gè)抽象類(類名用斜體表示),具有兩個(gè)float類型的

    公有

      • 的(共有用**+號(hào)**)成員變量numA和numB以及一個(gè)GetResult公有方法四個(gè)計(jì)算類繼承(

    繼承

    空心三角+實(shí)線

      • 表示)運(yùn)算類,并實(shí)現(xiàn)對(duì)應(yīng)的GetResult方法簡(jiǎn)單工廠類依賴于(

    依賴

    箭頭+虛線

    表示)運(yùn)算類,通過createOperation方法實(shí)現(xiàn)運(yùn)算類的實(shí)例化

3 總結(jié)

本篇主要介紹設(shè)計(jì)模式中的簡(jiǎn)單工廠模式,首先通過一個(gè)活字印刷的小故事來體會(huì)程序設(shè)計(jì)中的可維護(hù)、可復(fù)用、可擴(kuò)展、靈活性的思想,并引入面向?qū)ο笤O(shè)計(jì)模式中的三大基本思想:封裝、繼承、多態(tài),然后通過一個(gè)計(jì)算器的代碼實(shí)現(xiàn)的例子,通過C++實(shí)現(xiàn)了三個(gè)版本的代碼,由淺到深地理解面向?qū)ο蟮脑O(shè)計(jì)思想以及簡(jiǎn)單工廠模式的使用。

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
HFBR-1521ETZ 1 Foxconn Transmitter, 5Mbps, Through Hole Mount, ROHS COMPLIANT, 6 PIN
$17.77 查看
HCNW3120#300 1 Avago Technologies 1 CHANNEL LOGIC OUTPUT OPTOCOUPLER, 0.300 INCH, SURFACE MOUNT, DIP-8
$4.78 查看
TFDU6108-TT3 1 Vishay Intertechnologies Switch, Surface Mount,
暫無數(shù)據(jù) 查看

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄
浙江省| 阿拉尔市| 宜兰县| 绥化市| 嘉义县| 马龙县| 泾阳县| 二连浩特市| 洪湖市| 景东| 大同市| 灵璧县| 惠安县| 西盟| 牙克石市| 女性| 越西县| 岗巴县| 阜新市| 威海市| 灵寿县| 东港市| 读书| 桦甸市| 双流县| 呈贡县| 加查县| 阳原县| 林甸县| 水富县| 龙陵县| 朝阳市| 黄陵县| 余江县| 遵化市| 胶南市| 中西区| 新龙县| 两当县| 紫金县| 天等县|