利用シナリオ
ステートモード: オブジェクトの状態の変化に伴ってオブジェクトの動作が変化する場合、複数の判定条件を切り離し、動作の変化をカプセル化するため、オブジェクト動作インターフェイスを提供する抽象状態クラスを定義できます。特定の状態関連の動作は、そのサブクラスによって実装されます。
Strategy モード: 「戦略」という言葉はアルゴリズムに相当します。アルゴリズムを実際のシステムで動的に指定する必要があり、相互に置き換えることができる場合、アルゴリズムの呼び出しインターフェイスを抽象化できます。アルゴリズムは特定の戦略ロールによって実装されており、リスコフ置換原則に従って実装するには、親クラスが出現するあらゆる場所をそのサブクラスに置き換えることができ、これはビジネス ニーズを満たします。
比較
どちらも親クラスの標準呼び出しインターフェイスを抽象化していますが、特定の動作はサブクラスによって実装され、環境オブジェクトには親への参照も含まれています。クラスですが、これら 2 つのモードのアプリケーション シナリオはまったく異なります。例: ATM にお金を引き出しに行った場合、口座が凍結されている場合は、正常にお金を引き出すことができません。ここで、銀行口座には、凍結と凍結解除という少なくとも 2 つのステータスがあります。このようなビジネス ソリューションを解決するために戦略パターンを使用することは考えられないでしょう。もう 1 つの例は、ショッピング モールの割引です。さまざまな割引戦略があります。子供向けの商品は 30% オフ、高齢者の商品は 50% オフです。この問題は状態モードとは関係ありません。ここの商品には高齢者向けの商品があるとは言えません。状態と子状態です!
ATM 引き出しケース分析
設計された役割: レジ担当者、アカウント、ATM 機。
ユースケース図
わかりやすくするために、出金のユースケースを分析してみましょう。
基本イベント パス
(1) 引き出し者は銀行カードを挿入し、パスワードを入力します;
(2) 引き出しを選択します操作して出金金額を入力します;
(3) お金を引き出すために現金の引き出しを待ちます。
この使用例では、引き出し者のアカウントが凍結されている場合、オプションのイベント パスが発生し、引き出しの使用例は終了します。
主要なビジネス要件は、ユーザーがお金を引き出すという事実であるため、ドメイン モデリングは、引き出し者と引き出し者を識別する 2 つのクラスから開始できます。引き出し者にはお金を引き出すというユースケースがあるだけではないことを考慮して、引き出しをトランザクションに一般化します。
モデリング
ユースケースの実現
撤回: 基本的なイベント パスの実現。
洗練されたドメイン モデル
ATMSystem 境界オブジェクトは、ユーザーとの対話を担当するコントローラー (ユーザーと対話するための ATM 操作インターフェイス) としてここで紹介されています。 ). Trade は、ユーザー トランザクションの処理を担当するクラスです。
引き出し者は銀行カードを挿入し、パスワードを入力します。ATMSystem は、口座情報を確認するメッセージを取引トランザクション クラスに渡す責任があります。取引は、渡された口座パスワードに基づいてユーザーが存在するかどうかを確認し、その後、処理完了メッセージを ATMSystem に渡し、境界オブジェクトがユーザーに反映されます。
分析モデルのいくつかのクラス
##出金設計——申請ステータス モードアカウントのステータスは凍結ステータスに分けられますおよびアクティベーションステータス。アカウントはアクティブ化されている場合は取引を行うことができますが、凍結されている場合は取引を行うことができません。アカウント認証時には現在のアカウントのステータスが返される必要がありますが、アカウントが凍結されている場合は、出金操作を実行すると直接エラー メッセージが返されます。状態図は次のように表されます: 出金申請状態モード構造図: アカウント検証段階、アカウントが凍結状態の場合は、DeadAccount に直接戻ってすべてのトランザクションを拒否します。それ以外の場合は、ActiveAccount に戻って後続のトランザクションを処理します。 回路図コード: 実装を簡単にするため、境界オブジェクト ATMSystem はここでは省略されています。 ユーザーアカウント情報抽象クラス/// <summary> /// 用户账号信息 /// </summary> public abstract class Account { /// <summary> /// 账号 /// </summary> private string account; /// <summary> /// 密码 /// </summary> private string pwd; public abstract decimal getBalance(decimal d); }
/// <summary> /// 冻结账户类 /// </summary> public class DeadAccount:Account { public override decimal getBalance(decimal d) { return 0; } }
具体策略角色
/// <summary> /// 秋装打折策略 /// </summary> public class AutumnDressDiscountStrategy:IDiscountStrategy { #region IDiscountStrategy Members public decimal GetDiscount(goods g) { return (decimal)0.9 * g.Price; } #endregion } /// <summary> /// 运动鞋打折策略 /// </summary> public class SportShoesDiscountStrategy:IDiscountStrategy { #region IDiscountStrategy Members public decimal GetDiscount(goods g) { return g.Price * (decimal)0.8; } #endregion }
购物车
/// <summary> /// 购物车类 负责商品的维护 /// </summary> public class ShoppingCar { private List<goods> goodsList=new List<goods>(); /// <summary> /// 将商品加入到购物车 /// </summary> /// <param name="g"></param> public void AddGoods(goods g) { goodsList.Add(g); } /// <summary> /// 将商品从购物车当中移除 /// </summary> /// <param name="g"></param> public void RemoveGoods(goods g) { goodsList.Remove(g); } public List<goods> GoodsList { get { return goodsList; } } } |
收银台角色
/// <summary> /// 收银台 /// </summary> public class CashierDesk { /// <summary> /// 购物车 /// </summary> private ShoppingCar shoppingCar; /// <summary> /// 策略字典 /// </summary> private Dictionary<string, IDiscountStrategy> strategies; public CashierDesk(ShoppingCar sc, Dictionary<string, IDiscountStrategy> s) { this.shoppingCar = sc; this.strategies = s; } /// <summary> /// 获得所有商品的价格 /// </summary> /// <returns></returns> public decimal GetTotalPrice() { return shoppingCar.GoodsList.Sum(p => p.Price); } /// <summary> /// 获得所有商品的总的折扣 /// </summary> /// <returns></returns> public decimal GetTotalDiscount() { decimal sum = 0; IDiscountStrategy idiscountStrategy; foreach (goods g in shoppingCar.GoodsList) { idiscountStrategy=strategies.SingleOrDefault(p => p.Key == g.Type).Value; if (idiscountStrategy != null) { sum += idiscountStrategy.GetDiscount(g); } } return sum; } }
客户端代码
class Client { static void Main(string[] args) { ShoppingCar sc = new ShoppingCar(); Dictionary<string, IDiscountStrategy> discountD = new Dictionary<string, IDiscountStrategy>(); //向购物车中加入商品 sc.AddGoods(new goods {Name="NIKE鞋 ",Price=100,Type="运动鞋" }); sc.AddGoods(new goods { Name = "秋装", Price = 200, Type = "秋装" }); sc.AddGoods(new goods { Name = "苹果", Price = 300, Type = "水果" }); //配置折扣策略 discountD.Add("运动鞋", new SportShoesDiscountStrategy()); discountD.Add("秋装", new AutumnDressDiscountStrategy()); CashierDesk cd = new CashierDesk(sc, discountD); //得到所有商品总价 Console.WriteLine(cd.GetTotalPrice()); //得到所有商品折扣价 Console.WriteLine(cd.GetTotalDiscount()); Console.ReadLine(); } }
策略模式优点与缺点:
优点
封装了算法不稳定性,易于以后业务策略的扩展。
缺点
每种策略对应于一个具体策略角色类,会增加系统需要维护的类的数量。
以上がJavaデザインパターンにおける戦略パターンと状態パターンの分析例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。