小白菜成長記-應用設計模式

来源:http://www.cnblogs.com/yangsofter/archive/2017/05/15/design-mode.html
-Advertisement-
Play Games

工廠方法模式(Factory Method) 工廠方法屬於創建型模式中的一種,用於在不指定待創建對象的具體類的情況下創建對象,隱藏了對象創建的複雜性。客戶面向介面或抽象類進行編碼,而Factory類負責具體類的創建。通常,Factory類有一個返回介面或抽象類的靜態方法,客戶提供某種信息,然後由根據 ...


工廠方法模式(Factory Method)

工廠方法屬於創建型模式中的一種,用於在不指定待創建對象的具體類的情況下創建對象,隱藏了對象創建的複雜性。客戶面向介面或抽象類進行編碼,而Factory類負責具體類的創建。通常,Factory類有一個返回介面或抽象類的靜態方法,客戶提供某種信息,然後由根據信息來確定創建並返回哪個子類。
代碼示例

    //構建簡單的領域模型-Order訂單和Address送貨地址

    public class Address
    {
        public string CountryCode { get; set; }
    }

    public class Order
    {
        public decimal TotalCost { get; set; }
        public decimal WeightInKG { get; set; }
        public string CourierTrackingId { get; set; }
        public Address DispatchAddress { get; set; }
    }

    //為貨運公司創建介面,並添加兩個介面實現

    public interface IShippingCourier
    {
        string GenerateConsingnmentLableFor(Address address);
    }

    public class DHL : IShippingCourier
    {
        public string GenerateConsingnmentLableFor(Address address)
        {
            return "DHL-XXXX-XXXX-XXXX";
        }
    }

    public class RoyalMail : IShippingCourier
    {
        public string GenerateConsingnmentLableFor(Address address)
        {
            return "RMXXXX-XXXX-XXXX";
        }
    }
   
    /// <summary>
    /// 工廠類的根據訂單的價格和重量來確定使用哪一家貨運公司
    /// </summary>
    public static class UKShippingCourierFactory
    {
        public static IShippingCourier CreateShippingCourier(Order order)
        {
            if (order.TotalCost > 100 || order.WeightInKG > 5)
            {
                return new DHL();
            }
            else
            {
                return new RoyalMail();
            }
        }
    }

    public class OrderService
    {
        /// <summary>
        /// Dispatch方法只是協調有效的貨運公司的獲取以及托運標識符的創建;UKShippingCourierFactory工廠類在該實例中只負責根據某種業務規則創建有效的貨運公司;
        /// 通過將業務邏輯抽象出來放到工廠類中,為OrderService類減輕了負擔,使其關註與單一職責。
        /// 如果新增了貨運公司,只需要修改工廠類而不會影響到Service類,讓代碼與依賴類解耦,更易於維護。
        /// </summary>
        public void Dispatch(Order order)
        {
            IShippingCourier shippingCourier = UKShippingCourierFactory.CreateShippingCourier(order);
            shippingCourier.GenerateConsingnmentLableFor(order.DispatchAddress);
        }
    }

裝飾器模式(Decorator)

裝飾器模式屬於結構型模式中的一種,可以通過組合動態地向現有的對象添加新的行為或狀態,也就是說擴展動態現有類的功能。該模式的實現方式:
-從同一個基類繼承;
-實現一個共用的介面並註入待裝飾類的實例。

代碼示例

    //創建Product和Price的簡單模型,以及IPrice的介面實現裝飾對象

    public interface IPrice
    {
        decimal Cost { get; set; }
    }

    public class Product
    {
        public IPrice Price { get; set; }
    }

    public class BasePrice : IPrice
    {
        public decimal Cost { get; set; }
    }

    /// <summary>
    /// 包裝了IPrice介面的實現,將價格打88折
    /// </summary>
    public class TradeDiscountPriceDecorator : IPrice
    {
        private IPrice _basePrice;
        public TradeDiscountPriceDecorator(IPrice price)
        {
            _basePrice = price;
        }

        public decimal Cost
        {
            get
            {
                return _basePrice.Cost * 0.88m;
            }

            set
            {
                _basePrice.Cost = value;
            }
        }
    }

    /// <summary>
    /// CurrencyPriceDecorator和TradeDiscountPriceDecorator一樣,只不過是折扣由構造器傳入
    /// </summary>
    public class CurrencyPriceDecorator : IPrice
    {
        private IPrice _basePrice;
        private decimal _exchangeRate;

        public CurrencyPriceDecorator(IPrice price, decimal exchangeRate)
        {
            _basePrice = price;
            _exchangeRate = exchangeRate;
        }

        public decimal Cost
        {
            get
            {
                return _basePrice.Cost * _exchangeRate;
            }

            set
            {
                _basePrice.Cost = value;
            }
        }
    }

    /// <summary>
    /// 添加一組擴展方法,將裝飾器應用到Product類
    /// </summary>
    public static class ProductCollectionExtensionMethods
    {
        public static void ApplyCurrencyMultiplier(this IEnumerable<Product> products)
        {
            foreach (var p in products)
            {
                p.Price = new CurrencyPriceDecorator(p.Price, 0.5m);
            }
        }

        public static void ApplyTradeDiscount(this IEnumerable<Product> products)
        {
            foreach (var p in products)
            {
                p.Price = new TradeDiscountPriceDecorator(p.Price);
            }
        }
    }

    /// <summary>
    /// 獲取產品數據的介面
    /// </summary>
    public interface IProductRepository
    {
        IEnumerable<Product> FindAll();
    }

    /// <summary>
    /// ProductService職責是檢索並應用折扣和現金成數,而不用關註如何實現折扣和現金乘數
    /// </summary>
    public class ProductService
    {
        private IProductRepository _productService;
        public ProductService(IProductRepository productService)
        {
            _productService = productService;
        }

        public IEnumerable<Product> GetAllProducts()
        {
            IEnumerable<Product> products = _productService.FindAll();
            products.ApplyTradeDiscount();
            products.ApplyCurrencyMultiplier();
            return products;
        }
    }

裝飾器模式還經常應用於AOP(面向切麵編程),這個話題以後小白菜再來分享。

模板方法模式(Template Method)

模板方法模式是行為型模式的一種,由抽象類定義了演算法的模板並將具體實現推遲給子類去實現。
代碼示例

    /// <summary>
    /// 退貨方式:無條件退貨、有缺陷退貨
    /// </summary>
    public enum ReturnAction
    {
        FaultyReturn = 0,
        NoQuibblesReturn = 1
    }

    /// <summary>
    /// 退貨訂單
    /// </summary>
    public class ReturnOrder
    {
        public ReturnAction Action { get; set; }
        //訂單原始支付
        public string PaymentTransactionId { get; set; }
        //訂單總價
        public decimal PricePaid { get; set; }
        //運費
        public decimal PostageCost { get; set; }
        //退貨商品標識
        public long ProductId { get; set; }
        //退還客戶總金額
        public decimal AmountToRefund { get; set; }
    }

    /// <summary>
    /// 創建模板方法,具體的缺陷退貨和無條件退貨的處理交由子類去重寫
    /// </summary>
    public abstract class ReturnProcessTemplate
    {
        protected abstract void GenerateReturnTransactionFor(ReturnOrder returnOrder);
        protected abstract void CalculateRefoundFor(ReturnOrder returnOrder);

        public void Process(ReturnOrder returnOrder)
        {
            GenerateReturnTransactionFor(returnOrder);
            CalculateRefoundFor(returnOrder);
        }
    }

    public class NoQuibblesReturnProcess : ReturnProcessTemplate
    {
        protected override void CalculateRefoundFor(ReturnOrder returnOrder)
        {
            returnOrder.AmountToRefund = returnOrder.PricePaid;
        }

        protected override void GenerateReturnTransactionFor(ReturnOrder returnOrder)
        {
            //
        }
    }

    public class FaultyReturnProcess : ReturnProcessTemplate
    {
        protected override void CalculateRefoundFor(ReturnOrder returnOrder)
        {
            returnOrder.AmountToRefund = returnOrder.PricePaid + returnOrder.PostageCost;
        }

        protected override void GenerateReturnTransactionFor(ReturnOrder returnOrder)
        {
            //
        }
    }

    /// <summary>
    /// 工廠方法創建退貨的具體類型
    /// </summary>
    public static class ReturnProcessFactory
    {
        public static ReturnProcessTemplate CreateFrom(ReturnAction returnAction)
        {
            switch (returnAction)
            {
                case ReturnAction.FaultyReturn:
                    return new FaultyReturnProcess();
                case ReturnAction.NoQuibblesReturn:
                    return new NoQuibblesReturnProcess();
                default:
                    throw new ApplicationException("沒有定義" + returnAction.ToString() + "的處理");
            }
        }
    }

    public class ReturnService
    {
        public void Process(ReturnOrder returnOrder)
        {
            ReturnProcessTemplate returnProcess = ReturnProcessFactory.CreateFrom(returnOrder.Action);
            returnProcess.Process(returnOrder);
        }
    }

狀態模式(State)

狀態模式也是行為型模式中的一種,它允許對象在其內部狀態發生變化時改變自己的行為。將所有依賴狀態的行為交由單獨的子類去實現,避免了每個調用行為之前過多的去關註對象的狀態。
示例代碼

    public interface IOrderState
    {
        bool CanShip(Order order);
        void Ship(Order order);
        bool CanCancel(Order order);
        void Cancel(Order order);
        OrderStatus Status { get; }
    }

    public enum OrderStatus
    {
        New = 0,
        Shippend,
        Canceled
    }

    public class Order
    {
        private IOrderState _orderState;
        public Order(IOrderState baseState)
        {
            _orderState = baseState;
        }

        public int Id { get; set; }
        public string Customer { get; set; }
        public DateTime OrderedDate { get; set; }

        public OrderStatus Status()
        {
            return _orderState.Status;
        }

        public bool CanCancel()
        {
            return _orderState.CanCancel(this);
        }

        public void Cancel()
        {
            if (CanCancel())
            {
                _orderState.Cancel(this);
            }
        }

        public bool CanShip()
        {
            return _orderState.CanShip(this);
        }

        public void Ship()
        {
            if (CanShip())
            {
                _orderState.Ship(this);
            }
        }

        internal void Change(IOrderState orderState)
        {
            _orderState = orderState;
        }
    }

    /// <summary>
    /// 訂單已被取消
    /// </summary>
    public class OrderCanceledState : IOrderState
    {
        public OrderStatus Status
        {
            get
            {
                return OrderStatus.Canceled;
            }
        }

        public bool CanCancel(Order order)
        {
            return false;
        }

        public void Cancel(Order order)
        {
            throw new NotImplementedException();
        }

        public bool CanShip(Order order)
        {
            return false;
        }

        public void Ship(Order order)
        {
            throw new NotImplementedException();
        }
    }

    /// <summary>
    /// 訂單已發貨
    /// </summary>
    public class OrderShippedState : IOrderState
    {
        public bool CanCancel(Order order)
        {
            return false;
        }

        public void Cancel(Order order)
        {
            throw new NotImplementedException();
        }

        public bool CanShip(Order order)
        {
            return false;
        }

        public void Ship(Order order)
        {
            throw new NotImplementedException();
        }

        public OrderStatus Status { get { return OrderStatus.Shippend; } }
    }

    /// <summary>
    /// 新訂單
    /// </summary>
    public class OrderNewState : IOrderState
    {
        public OrderStatus Status
        {
            get
            {
                return OrderStatus.New;
            }
        }

        public bool CanCancel(Order order)
        {
            return true;
        }

        public void Cancel(Order order)
        {
            throw new NotImplementedException();
        }

        public bool CanShip(Order order)
        {
            return true;
        }

        public void Ship(Order order)
        {
            throw new NotImplementedException();
        }
    }

策略模式(Strategy)

策略模式也是行為型模式的一種,就是將演算法與其宿主分離,並能夠在運行時動態地切換演算法。策略模式將演算法封裝成對象,客戶代碼通過抽象類或介面來引用這些演算法。

    public interface IBasketDicountStrategy
    {
        decimal GetTotalCostAfterApplyingDiscountTo(Basket basket);
    }

    public class BasketDiscountMoneyOff : IBasketDicountStrategy
    {
        public decimal GetTotalCostAfterApplyingDiscountTo(Basket basket)
        {
            if (basket.TotalCost > 100)
            {
                return basket.TotalCost - 10.0m;
            }
            if (basket.TotalCost > 50)
            {
                return basket.TotalCost - 5.0m;
            }
            else
            {
                return basket.TotalCost;
            }
        }
    }

    public class BasketDiscountPercentageOff : IBasketDicountStrategy
    {
        public decimal GetTotalCostAfterApplyingDiscountTo(Basket basket)
        {
            return basket.TotalCost * 0.85m;
        }
    }

    public class NoBasketDiscount : IBasketDicountStrategy
    {
        public decimal GetTotalCostAfterApplyingDiscountTo(Basket basket)
        {
            return basket.TotalCost;
        }
    }

    public enum DiscountType
    {
        NoDiscount = 0,
        MoneyOff,
        PercentageOff
    }

    public class BasketDiscountFactory
    {
        public static IBasketDicountStrategy GetDiscount(DiscountType discountType)
        {
            switch (discountType)
            {
                case DiscountType.MoneyOff:
                    return new BasketDiscountMoneyOff();
                case DiscountType.PercentageOff:
                    return new BasketDiscountPercentageOff();
                default:
                    return new NoBasketDiscount();
            }
        }
    }

    public class Basket
    {
        public decimal TotalCost { get; set; }

        private IBasketDicountStrategy _basketDiscount;

        public Basket(DiscountType discountType)
        {
            _basketDiscount = BasketDiscountFactory.GetDiscount(discountType);
        }

        public decimal GetTotalCostAfterDiscount()
        {
            return _basketDiscount.GetTotalCostAfterApplyingDiscountTo(this);
        }
    }

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 系統有些埠是我們平時用不到但是又存在危險的埠,例如139、135、445等埠,windows預設是開著的,這時我們可以手動關閉這些埠!下邊為大家介紹一種通過windows組策略來一次性關閉所有想要關閉的危險埠 系統有些埠是我們平時用不到但是又存在危險的埠,例如139、135、445等端 ...
  • 一.並行LINQ System.Linq名稱空間中包含的類ParallelEnumerable可以分解查詢的工作,使其分佈在多個線程上。 儘管Enumerable類給IEnumerable<T>介面定義了擴展方法,但ParallelEnumerable類的大多數擴展方法是ParallerQuery< ...
  • 原文鏈接:http://blog.csdn.net/hebbers/article/details/70332015 關鍵點在與 ...
  • 經常在項目中遇到定時任務的時候,通常第一個想到的是Timer定時器,但是這玩意功能太弱雞,實際上通常採用的是專業化的第三方調度框架,比如說 Quartz,它具有功能強大和應用的靈活性,我想使用過的人都非常瞭解,那麼本篇就來說說如何通過代碼和配置文件來進行job和trigger的配置。 一:常規的jo ...
  • 今天學習angularjs向資料庫添加數據。學習此篇,得從以往幾篇開始,因為那還有創建數據表等演示。現在來創建一個添加的存儲過程: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[usp_Goods_I ...
  • c 介面使用詳解 c 中介面隱式與顯示實現 c 中介面可以隱式實現、顯示實現,隱式實現更常使用、顯示實現較少使用 其區別在於 1. 顯示實現避免介面函數簽名衝突 2. 顯示實現只可以以介面形式調用 3. 顯示實現其子類需無法繼承介面 4. 隱式實現可以撕裂調用、可以介面調用 5. 隱式實現其子類可以 ...
  • 下載並引入兩個dll文件 NPinyin.dll 和 ChnCharInfo.dll 其實這兩個dll 任何一個都可以實現漢字轉拼音,然而 NPinyin.dll 收錄的漢字並不全,但是很人性化,能識別一些常用的漢字。ChnCharInfo.dll 是微軟的很全但是不人性化。另外本套代碼外有一個自己 ...
  • DotBPE.RPC是一款基於dotnet core編寫的RPC框架,而它的爸爸DotBPE,目標是實現一個開箱即用的微服務框架,但是它還差點意思,還僅僅在構思和嘗試的階段。但不管怎麼說RPC是微服務的基礎,先來講講RPC的實現吧。DotBPE.RPC底層通信預設實現基於[DotNetty](htt... ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...