Usage scenarios
State mode: When the behavior of an object changes with the change of the state of the object, in order to decouple multiple judgment conditions and encapsulate the changes in behavior, we can define a Abstract state class that provides object behavior interface. Specific state-related behaviors are implemented by its subclasses.
Strategy mode: The word "strategy" is equivalent to algorithm. When algorithms need to be dynamically specified in the real system and can be replaced with each other, the calling interface of the algorithm can be abstracted. The specific algorithm is implemented by a specific strategy role. To implement, according to the Liskov substitution principle, any place where a parent class appears can be replaced with its subclass, which meets our business needs.
Comparison
Although both abstract the standard calling interface of the parent class, the specific behavior is implemented by the subclass, and the environment object also contains references to the parent class, but The application scenarios of these two modes are completely different. For example: If you go to an ATM to withdraw money, if your account is frozen, you cannot withdraw money normally. Here, your bank account has at least two statuses: frozen and unfrozen. You would not think of using the strategy pattern to solve such a business solution. Another example is shopping mall discounts. There are many discount strategies. Children's products are 30% off, and elderly products are 50% off. This problem is not related to the state mode. You can't say that the products here have an elderly state and a child state!
ATM withdrawal case analysis
Designed roles: cashier, account, ATM machine.
Use case diagram
For the sake of simplicity, let’s analyze the withdrawal use case.
Basic event path
(1) The withdrawer inserts the bank card and enters the password;
(2) Selects the withdrawal operation and enters Withdrawal amount;
(3) Waiting for cash withdrawal to withdraw money.
In this use case, if the withdrawer's account has been frozen, an optional event path occurs and the withdrawal use case is terminated.
The key business requirement is the fact that the user withdraws money, so domain modeling can start from the two classes that identify the withdrawal and the withdrawal person. Taking into account that the withdrawr not only has the use case of withdrawing money, we generalize the withdrawal into a transaction.
Modeling
Use Case Realization
Withdrawal: Realization of the basic event path.
Refined domain model
The ATMSystem boundary object is introduced here as the controller responsible for interacting with the user (the ATM operation interface for interacting with the user). Trade is the class responsible for processing user transactions.
The withdrawer inserts the bank card and enters the password. ATMSystem is responsible for passing the message to verify the account information to the Trade transaction class. Trade verifies whether the user exists based on the passed account password, and then passes the processing completion message to ATMSystem. Boundary objects are reflected to the user.
Some classes in the analysis model
##Withdrawal design——Application status modeThe status of the account is divided into frozen status and Activation status. The account can conduct transactions when it is activated, but cannot make any transactions when it is frozen. During account verification, the status of the current account should be returned. If the account is frozen, an error message will be returned directly when the withdrawal operation is performed. The state diagram is represented as follows: Withdrawal application state mode structure diagram: In the account verification stage, if the account is In the frozen state, it will directly return to DeadAccount to refuse all transactions, otherwise it will return to ActiveAccount to process subsequent transactions. Schematic code: For simple implementation, the boundary object ATMSystem is omitted here. User account information abstract class/// <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(); } }
策略模式优点与缺点:
优点
封装了算法不稳定性,易于以后业务策略的扩展。
缺点
每种策略对应于一个具体策略角色类,会增加系统需要维护的类的数量。
The above is the detailed content of Example analysis of strategy pattern and state pattern in java design patterns. For more information, please follow other related articles on the PHP Chinese website!