1. 程式人生 > >大話設計模式筆記——策略模式

大話設計模式筆記——策略模式

本篇內容為博主個人在學習《大話設計模式》(程傑 著)過程中的測試隨筆,在此給各位程式設計新手作為學習參考,畢竟網上深入學習的資料對於瓶頸期的新人大多不太友好,我會盡量詳細的展示並解釋每一個細節,也歡迎大家對我的不足給予批評指正。

這週一直在加班,今天終於早點下班了,繼續把上週學習的內容記錄一下。

本篇以商場收銀軟體應對多變的折扣策略為例,為我們展示如何把變化的演算法封裝起來,讓它與業務隔離,同時減小程式的耦合度,讓演算法的變化不會影響到使用演算法的客戶。

專案目錄如下

在這裡插入圖片描述

一、運算業務基類

結算業務類基類(BaseCharge)定義了一個計算金額的虛方法(CountMoney())。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class BaseCharge
    {
       /// <summary>
       /// 計算金額
       /// </summary>
       /// <param name="TotalPrice">應收款</param>
       /// <returns>實收款</returns>
        public virtual double CountMoney(double TotalPrice)
        {
            return TotalPrice;
        }
    }
}

二、按折扣計算金額演算法類

繼承結算業務類基類(BaseCharge),重寫基類方法CountMoney(),實現對應收款的打折後實付款演算法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class ChargeByDiscount : BaseCharge
    {
        /// <summary>
        /// 折扣率
        /// </summary>
        private double DiscountRate;

        /// <summary>
        /// 建構函式,將傳入的折扣率賦值
        /// </summary>
        /// <param name="discountRate">折扣率</param>
        public ChargeByDiscount(string discountRate)
        {
            DiscountRate = Convert.ToDouble(discountRate);
        }

        /// <summary>
        /// 重寫基類計算價格的方法
        /// </summary>
        /// <param name="TotalPrice">應收款</param>
        /// <returns>實付款</returns>
        public override double CountMoney(double TotalPrice)
        {
            return TotalPrice * DiscountRate;
        }
    }
}

三、按滿減計算金額演算法類

繼承結算業務類基類(BaseCharge),重寫基類方法CountMoney(),實現對應收款的滿減後實付款演算法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class ChargeByFullSub : BaseCharge
    {
        /// <summary>
        /// 條件金額
        /// </summary>
        public double ConditionalMoney = 0;
        /// <summary>
        /// 減免金額
        /// </summary>
        public double SubMoney = 0;

        /// <summary>
        /// 建構函式
        /// </summary>
        /// <param name="conditionalMoney">條件金額</param>
        /// <param name="subMoney">減免金額</param>
        public ChargeByFullSub(double conditionalMoney, double subMoney)
        {
            ConditionalMoney = conditionalMoney;
            SubMoney = subMoney;
        }

        /// <summary>
        /// 重寫基類計算價格的方法
        /// </summary>
        /// <param name="TotalPrice">應收款</param>
        /// <returns>實付款</returns>
        public override double CountMoney(double TotalPrice)
        {
            return TotalPrice - Math.Floor(TotalPrice / ConditionalMoney) * SubMoney;
        }
    }
}

四、按原價計算金額演算法類

繼承結算業務類基類(BaseCharge),重寫基類方法CountMoney(),實現對應收款的原價計算實付款演算法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class ChargeByNormal : BaseCharge
    {
        /// <summary>
        /// 重寫基類計算價格的方法
        /// </summary>
        /// <param name="TotalPrice">應收款</param>
        /// <returns>實付款</returns>
        public override double CountMoney(double TotalPrice)
        {
            return TotalPrice;
        }
    }
}

五、Context上下文

定義一個演算法例項oCharge ,通過簡單工廠模式獲取相應的演算法類例項,呼叫各個演算法類重寫的基類計算金額方法來計算應付款。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StrategyTest.Business
{
    class ChargeContext
    {
        /// <summary>
        /// 定義一個演算法例項
        /// </summary>
        BaseCharge oCharge = null;

        /// <summary>
        /// 建構函式,同時利用簡單工廠模式,獲取對應的計算類例項
        /// </summary>
        /// <param name="CountType">計算型別字串</param>
        public ChargeContext(string CountType)
        {
            switch (CountType)
            {
                case "正常收費":
                    this.oCharge = new ChargeByNormal();
                    break;
                case "打八折":
                    this.oCharge = new ChargeByDiscount("0.8");
                    break;
                case "滿400減50":
                    this.oCharge = new ChargeByFullSub(400, 50);
                    break;
            }
        }

        /// <summary>
        /// 獲取最終實付款金額
        /// </summary>
        /// <param name="TatolPrices">應收款</param>
        /// <returns>實付款</returns>
        public double GetResultPrices(double TatolPrices)
        {
            return oCharge.CountMoney(TatolPrices);
        }

    }
}

六、WinFrom後臺程式碼

WinFrom介面如下
在這裡插入圖片描述

WinFrom後臺程式碼

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using StrategyTest.Business;

namespace StrategyTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btn_Count_Click(object sender, EventArgs e)
        {
            double oTotalPrices = 0;

            //簡單工廠寫法
            //BaseCharge oCharge = ChargeContext.InstantiationCharge(cmb_CountType.SelectedItem.ToString());
            //oTotalPrices = oCharge.CountMoney(Convert.ToDouble(txt_UnitPrice.Text.Trim()) * Convert.ToDouble(txt_Num.Text.Trim()));

            //策略加簡單工廠寫法

            ChargeContext oChargeContext = new ChargeContext(cmb_CountType.SelectedItem.ToString());
            oTotalPrices = oChargeContext.GetResultPrices(Convert.ToDouble(txt_UnitPrice.Text.Trim()) * Convert.ToDouble(txt_Num.Text.Trim()));
            lab_Total.Text = oTotalPrices.ToString();
        }
    }
}

個人理解策略模式主要用來封裝各種業務規則,比如ORM框架中可用於實現封裝不同型別資料庫的增刪改查方法等,目前對這個演算法的理解還是不太透徹,希望以後遇到實際需求時,能夠用得上它。