あなたの例では、特定の製品に適用されるデコレータのチェーンを示しています。
var discountA = new BuyXGetYFreeDecorator(product, itemsToApplyTheDiscount, itemsYouGetFree);
var discountB = new FixedDiscountDecorator(discountA, discountPercentage);
質問は、product
上記のコードから構築された、指定されたプロパティによって管理される状態を変更するために使用できるいくつかのパターンは何ですか? あなたの例を使用して、私の範囲をproduct
コストの決定に限定します。
public interface IComponent
{
decimal GetCost { get; set; }
}
IComponent を表す製品クラスを作成します
public class Product
{
public IComponent Price { get; set; }
}
デコレータ クラスに加えて、「デフォルト」の実装がある場合があります。
public class BasePrice : IComponent
{
private Decimal _cost;
public decimal GetCost //as a property maybe use Cost with get; set; in IComponent
{
get { return _cost; }
set { _cost = value; }
}
}
IoC を使用し、IComponent からコストのバリエーション (GetCost()) を実装する 2 つのデコレータ クラスが気に入っています。
ここまでは、基本価格クラスのみで、何も追加していません。次に私ができることは、テンプレート メソッド パターンに示されているように、抽象クラスを使用し、特定の操作をサブクラスに任せることです。私の具体的なクラスは、この基本クラスから継承します。作成される具象クラスは、Factory メソッド パターンに渡されるアクション タイプに依存します。このクラスは、以下で WarrantyProcessFactory と呼ばれます。
あなたはapp.configを使用すると言いました...私は、適用されるアクションタイプを指定するために使用する列挙型が好きproduct
です。たとえば、製品の保証に基づいて製品を処理できるように、アクションを製品の保証に関連付けたいとします。
public enum WarrantyAction
{
RefundProduct = 0,
ReplaceProduct = 1
}
保証要求クラスを使用して、欠陥製品に対する顧客からの補償要求を表します
public class WarrantyRequest
{
public WarrantyAction 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; }
}
最後に、保証アクション列挙型を表す具象クラスによってオーバーライドされる抽象テンプレート メソッドを実装できます。
public abstract class WarrantyProcessTemplate
{
protected abstract void GenerateWarrantyTransactionFor(WarrantyRequest warrantyRequest);
protected abstract void CalculateRefundFor(WarrantyRequest warrantyRequest);
public void Process(WarrantyRequest warrantyRequest)
{
GenerateWarrantyTransactionFor(warrantyRequest);
CalculateRefundFor(warrantyRequest);
}
}
クラスと最初の 2 つのメソッドは抽象的であり、サブクラスによって実装する必要があります。3 番目のメソッドは、単純に 2 つの抽象メソッドを呼び出して、WarrantyRequest エンティティを引数として渡します。
お客様が返金を希望するケース
public class RefundWarrantyProcess : WarrantyProcessTemplate
{
protected override void GenerateWarrantyTransactionFor(WarrantyRequest warrantyRequest)
{
// Code to determine terms of the warranty and devalutionAmt...
}
protected override void CalculateRefundFor(WarrantyRequest warrantyRequest)
{
WarrantyRequest.AmountToRefund = warrantyRequest.PricePaid * devalutionAmt;
}
}
代替品をご希望の場合
public class ReplaceWarrantyProcess : WarrantyProcessTemplate
{
protected override void GenerateWarrantyTransactionFor(WarrantyRequest warrantyRequest)
{
// Code to generate replacement order
}
protected override void CalculateRefundFor(WarrantyRequest warrantyRequest)
{
WarrantyRequest.AmountToRefund = warrantyRequest.PostageCost;
}
}
public static class WarrantyProcessFactory
{
public static WarrantyProcessTemplate CreateFrom(WarrantyAction warrantyAction)
{
switch (warrantyAction)
{
case (WarrantyAction.RefundProduct):
return new RefundWarrantyProcess();
case (WarrantyAction.ReplaceProduct):
return new ReplaceWarrantyProcess();
default:
throw new ApplicationException(
"No Process Template defined for Warranty Action of " +
warrantyAction.ToString());
}
}
}
私が検討するもう 1 つのパターンは、Strategy Method パターンです。この場合、Context クラスは、その抽象クラスまたはインターフェースによって参照される「ConcreteStrategy」にすべての計算を任せます。Scott Millet の著書「Professional ASP.NET Design Patterns」が有用なリソースであることがわかり、よく読み返しています。
私はコメントや批判を受け付けています。