1. 程式人生 > >簡單工廠+策略模式-下

簡單工廠+策略模式-下

前言:

         雖然做了個Demo但是實際應用的時候發現一開始對簡單工廠與策略的理解有誤差、開始想輸入時間和基礎資料就根據不同的演算法算出來、後來發現不是、其實時間也是計算的資料、真正選擇演算法的是像固定使用者和臨時使用者、或者說打折促銷、根據這個。

深夜食堂

          一個在深夜12點到凌晨7點開張的小食店、被大家稱謂深夜食堂、選單上只有一樣菜、但是、無論你要點什麼、只要老闆會做、即使選單上沒有的菜也可以點、所以、客人還真不少呢。

          日式滑動的木門被開啟、進來的是一個渾身又綠色、有著硬殼的傢伙、沒錯、他是富蘭克林、老闆,清酒、酒蒸蛤蜊。

          老闆一邊做著、一邊調侃道,怎麼了?又被老闆剝削了?富蘭克林緊攥拳頭、碰!敲桌子說道,

哼!看著吧!他那臭煤窯早晚塌了!賠死他個黑心鬼!

         清酒與酒蒸蛤蜊、老闆端了上來、滋滋滋……嗯!果然酒蒸蛤蜊跟清酒一起、最美味了、呦呦呦、這不是我們偉大的IT人士、富蘭克林嘛!肉白卡推門、探出頭說道。

          肉白卡……你怎麼也大晚上的來吃料理?哎、這不是上下機剛做完嘛、出來吃夜宵、怎麼龜龜漲工資了?都吃海鮮了?

           PEI!別提了、不打算幹了、那老闆給軟體輸入錢跟沒改一樣、而且這次有了軟體還不能鑽空子了、這不趕到這點剛下班= =、你上下機怎麼樣了?

        今天剛搞完、吶吶、還帶著UML圖呢、老闆、章魚燒三份、今天我心情好、富蘭克林你上次那個不太對、我改了改,最後也用上了、策略模式的所有策略都是可以互相替換的、你一個輸入2個數一個輸入3個數那啥玩應啊偷笑

去去去……的了便宜還賣乖、沒我的Demo、你能做出來?UML圖拿來


章魚燒、請慢用、哇真香、嗯!皮酥肉嫩、加上柴魚片和海苔絲、真是美味!

趕緊的!別廢話!富蘭克林叫到……

好好好、那咱先看抽象演算法類與演算法

            這裡我定義了兩個演算法、一個是上機臨時使用者的、一個是固定使用者的、每個演算法一個類、都繼承與演算法抽象類、都有一個演算法方法。這個沒問題吧

           富蘭克林很鄙視的看著滿嘴章魚丸的肉白卡……繼續 - -

那說策略類

          策略類聲明瞭一個抽象演算法、生命的抽象演算法用的卻是子類、他有兩個方法、一個用於接收策略、另一個用於使用策略的方法、好處就不言而喻了、現在只有固定使用者和臨時使用者、我可以再加個打折演算法、直接在演算法抽象類下面加個類就好啦、啥程式碼都不用改。

          那工廠模式你咋仨方法了呀= =富蘭克林問到

          這個就要好好說下了、龜龜啊、你沒發現我比你多些了一個有很多變數和方法的類嗎?

          又下角的那個?countData?

          對!那是一個類似實體的類、裡面是計算要用的引數、如每小時的錢、是固定使用者還是臨時使用者、上機持續時間等、我工廠下的AddData方法就是把傳進來的2個實體和一個引數傳給countData、這樣就解了耦合、假如我這個演算法放到別的軟體中、只要改下AddData方法、把引數都對應上、其他程式碼就不用改了、如果直接用給的引數名或者引數計算、那換個地方、傳值的名字都要改。

           IFCount這是工廠的核心、根據傳進來是固定使用者還是臨時使用者、選擇演算法、NEW演算法類、返回一個演算法類的例項物件。

           CountMoney這個方法是我自己填的、他呼叫了AddData和IFCount並且最後使用了工廠給出的演算法物件、進行計算、簡單後所就是外界只要知道這個類的這一個方法、輸入值、方法就能直接返回Money結果。

            綜上所述、如果我加一個策略、只需要在抽象演算法類下加一個子類、改下工廠的IFCount、填一條小小的Case就好啦害羞、咋樣富蘭克林?

真是太……太精彩了……富蘭克林擦了擦臉上的章魚燒碎屑……說道

富蘭克林:這樣吧、我辭了工作跟你幹吧

          好呀!我們公司最近做專案正好有個人女程式設計師因為抑鬱、在宿舍那跳樓了、正好、你也是搞過的、應該沒問題!這樣吧、我給你這次的程式碼、你回去研究下。

''' <summary>
''' 簡單工廠類
''' </summary>
''' <remarks></remarks>
Public Class CashFactory



    ''' <summary>
    ''' 傳進演算法所需要的值、請確定值不為空
    ''' </summary>
    ''' <param name="bname">只能輸入-固定使用者-臨時使用者</param>
    ''' <param name="bComputerRecords"></param>
    ''' <param name="bBaseData"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function AddData(bname As String, bComputerRecords As Entity.EComputerRecords, bBaseData As Entity.EBaseData) As countData
        Dim countData As New countData '定義傳遞物件
        '(複製程式碼的話請把傳入值改了、並與此處一一對應上)
        '工廠判定
        'countData.str = bname
        countData.str = "固定使用者"
        '上機時間
        countData.consumeTime = bComputerRecords.ConsumeTime
        'countData.consumeTime = 35
        '準備時間
        countData.readyTime = bBaseData.ReadyTime
        'countData.readyTime = 5
        '固定使用者半小時費用
        countData.fixedMoney = bBaseData.FixedHalfHourMoney
        'countData.fixedMoney = 1
        '時間遞增單位
        countData.addTime = bBaseData.AddTime
        'countData.addTime = 5
        '最少上機時間
        countData.leastTime = bBaseData.LeastTime
        'countData.leastTime = 30
        '上機最少金額
        countData.LeastMoney = bBaseData.LeastMoney
        'countData.LeastMoney = 1

        Return countData
    End Function

    ''' <summary>
    ''' 選擇演算法、
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function IFCount(coutData As countData) As CashContext
        Dim fCashContext As New CashContext '定義策略
        Select Case (coutData.str)
            Case "固定使用者"
                fCashContext.CashContext(New LongTermUser())
            Case "臨時使用者"
                fCashContext.CashContext(New TemporaryUser())
            Case Else
                MsgBox("未找到相應演算法策略")
        End Select
        Return fCashContext
    End Function

    ''' <summary>
    ''' 方便呼叫(複製程式碼的話請把傳入值改了)
    ''' </summary>
    ''' <param name="bname"></param>
    ''' <param name="bComputerRecords"></param>
    ''' <param name="bBaseData"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CountMoney(bname As String, bComputerRecords As Entity.EComputerRecords, bBaseData As Entity.EBaseData) As Integer
        Dim countdata As New countData '儲存資料
        Dim fCashContext As New CashContext '儲存策略

        countdata = AddData(bname, bComputerRecords, bBaseData) '獲取資料(複製程式碼的話請把傳入值改了)
        fCashContext = IFCount(countdata) '獲取策略
        Return fCashContext.countMoney(countdata) '計演算法返回結果
    End Function
End Class

''' <summary>
''' 策略模式類
''' </summary>
''' <remarks></remarks>
Public Class CashContext

    Private insideCashAlgorithm As CashAlgorithm '宣告一個演算法抽象類

    ''' <summary>
    ''' 構造方法、接受外部傳入的演算法類(這裡宣告抽象演算法類、使用他的子類、也就是策略)
    ''' </summary>
    ''' <param name="outSideCashAlgorithm"></param>
    ''' <remarks></remarks>
    Public Sub CashContext(outSideCashAlgorithm As CashAlgorithm)
        insideCashAlgorithm = outSideCashAlgorithm
    End Sub

    ''' <summary>
    ''' 使用接受演算法的方法、計算出money返值
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function countMoney(coutData As countData) As Integer
        Return insideCashAlgorithm.countMoney(coutData)
    End Function

End Class

''' <summary>
''' 演算法抽象列(CashAlgorithm現金演算法)
''' </summary>
''' <remarks></remarks>
Public MustInherit Class CashAlgorithm

    ''' <summary>
    ''' 算現金的抽象方法
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overridable Function countMoney(coutData As countData) As Integer
        Dim money As Integer
        Return money
    End Function
    '必須被重寫
    'Public Overrides Sub Move(ByVal NewX As Integer, ByVal NewY As Integer)
    '    '...
    'End Sub
    'Public Property XPos() As Integer
    '    '...
    'End Property

End Class


''' <summary>
''' 演算法1 固定使用者
''' </summary>
''' <remarks></remarks>
Public Class LongTermUser

    '繼承抽象類
    Inherits CashAlgorithm

    ''' <summary>
    ''' 正常工資的演算法
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function countMoney(coutData As countData) As Integer
        Dim money As Integer '定義存放錢的變數

        '--1--判定上機時間是否大於準備時間、小於則不收錢
        If coutData.consumeTime < coutData.readyTime Then
            money = 0
            Return money
            Exit Function
        Else
            coutData.consumeTime = coutData.consumeTime - coutData.readyTime
        End If

        '--2--減去沒有到達遞增時間的時間(只取整)
        coutData.consumeTime = Fix(coutData.consumeTime / coutData.addTime) * coutData.addTime

        '---3---是否大於最小上機時間
        If coutData.consumeTime < coutData.leastTime Then
            coutData.consumeTime = coutData.leastTime
        End If

        '----4----算錢、有幾個半小時、多出半小時的按一個半小時算
        If coutData.consumeTime / 30 > Fix(coutData.consumeTime / 30) Then
            money = coutData.fixedMoney * (Fix(coutData.consumeTime / 30) + 1)
        Else
            money = coutData.fixedMoney * (coutData.consumeTime / 30)
        End If

        '---5-----是否大於上機最小金額
        If money < coutData.LeastMoney Then
            money = coutData.LeastMoney
        End If



        Return money '返回計算結果
    End Function
End Class


''' <summary>
''' 演算法2 臨時使用者
''' </summary>
''' <remarks></remarks>
Public Class TemporaryUser
    '繼承抽象類
    Inherits CashAlgorithm
    ''' <summary>
    ''' 節假日工資的演算法
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function countMoney(coutData As countData) As Integer
        Dim money As Integer '定義存放錢的變數
        money = 2 '這裡是正常工資的2倍
        Return money '返回計算結果
    End Function
End Class





''' <summary>
''' 計算下機、簡單工廠與策略模式傳值用
''' </summary>
''' <remarks></remarks>
Public Class countData
    '工廠選擇欄位
    Dim str_ As String
    '消費時間
    Dim ConsumeTime_ As New Integer
    '準備時間
    Dim ReadyTime_ As New Integer
    '固定使用者半小時費用
    Dim FixedMoney_ As New Integer
    '時間遞增單位
    Dim AddTime_ As New Integer
    '最少上機時間
    Dim LeastTime_ As New Integer
    '上機最少金額
    Dim LeastMoney_ As New Integer

    ''' <summary>
    ''' 傳入工廠選擇的字串
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property str() As String
        Get
            Return str_
        End Get
        Set(ByVal value As String)
            str_ = value
        End Set
    End Property

    ''' <summary>
    ''' 消費時間
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property consumeTime() As Integer
        Get
            Return ConsumeTime_
        End Get
        Set(ByVal value As Integer)
            ConsumeTime_ = value
        End Set
    End Property

    ''' <summary>
    ''' 準備時間
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property readyTime() As Integer
        Get
            Return ReadyTime_
        End Get
        Set(ByVal value As Integer)
            ReadyTime_ = value
        End Set
    End Property

    ''' <summary>
    ''' 固定使用者半小時費用
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property fixedMoney() As Integer
        Get
            Return FixedMoney_
        End Get
        Set(ByVal value As Integer)
            FixedMoney_ = value
        End Set
    End Property

    ''' <summary>
    ''' 時間遞增單位
    ''' </summary>
    ''' <remarks></remarks>
    Public Property addTime() As Integer
        Get
            Return AddTime_
        End Get
        Set(ByVal value As Integer)
            AddTime_ = value
        End Set
    End Property

    ''' <summary>
    ''' 最少上機時間
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property leastTime() As Integer
        Get
            Return LeastTime_
        End Get
        Set(ByVal value As Integer)
            LeastTime_ = value
        End Set
    End Property

    ''' <summary>
    ''' 上機最少金額
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property LeastMoney() As Integer
        Get
            Return LeastMoney_
        End Get
        Set(ByVal value As Integer)
            LeastMoney_ = value
        End Set
    End Property

End Class


現在臨時使用者的計算還沒寫、你可以試著寫下、張嘴

啊……嗯……章魚燒~

怎麼樣、還是烤章魚丸好吃吧、海鮮就是好吃、我這個酒蒸蛤蜊也是海鮮啊!又鮮又美味

哎!……富蘭克林、不對啊、你不也是海鮮嘛偷笑

切、那你和章魚燒、酒蒸蛤蜊還都是生物呢、我可是有手有腳、有腦袋的高階生物好不!

哈哈哈…………店長和肉白卡一起笑了

章魚燒


酒蒸蛤蜊


          深夜凌晨6點、肉白卡和醉醺醺的富蘭克林都回了家、每天深夜、12點到7點、深夜食堂、雖然選單上只有一道菜、但是隻要老闆會做、及時選單上沒有、也可以點、大家都吃著自己喜歡的食物、深夜、都講述著自己的故事。

總結:

       這次送大家兩道菜哈、最近越學設計模式、越感覺、做例子不等於實現了、能想通不代表能做通、只有不斷的實踐、實踐、實踐、才能越深入的瞭解和學習。

         記得剛上小學三年級、那時候剛學英語、學完了ABC、英語老師說我們剛剛英語入門、上了初中、還是學ABC加音標、初中老師說我們英語剛剛入門、到了TGB、學英語……我了個去、這次連門都進不去了、由此看來設計模式我還沒入門……蹲牆角畫圈ING

_____________________大家在程式設計的同時也不要忘了、我們是吃貨_____________________

—————————————chenchen—————————————