工廠方法模式(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);
}
}