parent
7cce2e2d34
commit
ebf7cddb25
@ -0,0 +1,236 @@ |
|||||||
|
namespace DesignPattern.Patterns |
||||||
|
{ |
||||||
|
public class StateMachinePattern |
||||||
|
{ |
||||||
|
public static void Work() |
||||||
|
{ |
||||||
|
VendingMachine vendingMachine = new VendingMachine(); |
||||||
|
|
||||||
|
while (true) |
||||||
|
{ |
||||||
|
Console.WriteLine("Please select action (AddMoney, SelectItem, ReturnChange)"); |
||||||
|
string input = Console.ReadLine(); |
||||||
|
string read; |
||||||
|
switch (input.ToUpper()) |
||||||
|
{ |
||||||
|
case "ADDMONEY": |
||||||
|
Console.Write("Money: "); |
||||||
|
read = Console.ReadLine(); |
||||||
|
int.TryParse(read, out int money); |
||||||
|
vendingMachine.AddMoney(money); |
||||||
|
break; |
||||||
|
case "SELECTITEM": |
||||||
|
Console.Write("ItemId: "); |
||||||
|
read = Console.ReadLine(); |
||||||
|
int.TryParse(read, out int itemId); |
||||||
|
vendingMachine.SelectItem(itemId); |
||||||
|
break; |
||||||
|
case "RETURNCHANGE": |
||||||
|
vendingMachine.ReturnChange(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class VendingMachine |
||||||
|
{ |
||||||
|
private Product product = new Product(); |
||||||
|
internal decimal Money { get; set; } |
||||||
|
|
||||||
|
internal VMState ReadyState { get; private set; } |
||||||
|
internal VMState HasMoneyState { get; private set; } |
||||||
|
internal VMState DispenseItemState { get; private set; } |
||||||
|
internal VMState DispenseChangeState { get; private set; } |
||||||
|
internal VMState State { get; set; } |
||||||
|
|
||||||
|
public VendingMachine() |
||||||
|
{ |
||||||
|
Money = 0; |
||||||
|
|
||||||
|
ReadyState = new ReadyState(this); |
||||||
|
HasMoneyState = new HasMoneyState(this); |
||||||
|
DispenseItemState = new DispenseItemState(this); |
||||||
|
DispenseChangeState = new DispenseChangeState(this); |
||||||
|
|
||||||
|
State = ReadyState; |
||||||
|
} |
||||||
|
|
||||||
|
public void AddMoney(decimal money) |
||||||
|
{ |
||||||
|
State.AddMoney(money); |
||||||
|
} |
||||||
|
|
||||||
|
public void SelectItem(int itemId) |
||||||
|
{ |
||||||
|
State.SelectItem(itemId); |
||||||
|
} |
||||||
|
|
||||||
|
public void ReturnChange() |
||||||
|
{ |
||||||
|
State.ReturnChange(Money); |
||||||
|
} |
||||||
|
|
||||||
|
internal decimal? GetPrice(int itemId) |
||||||
|
{ |
||||||
|
return product.GetPrice(itemId); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal class Product |
||||||
|
{ |
||||||
|
private List<Item> _items; |
||||||
|
|
||||||
|
public Product() |
||||||
|
{ |
||||||
|
_items = new List<Item>() |
||||||
|
{ |
||||||
|
new Item() { Id = 101, Price = 3.5M }, |
||||||
|
new Item() { Id = 201, Price = 4.0M }, |
||||||
|
new Item() { Id = 301, Price = 4.5M }, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
public decimal? GetPrice(int itemid) |
||||||
|
{ |
||||||
|
var item = _items.SingleOrDefault(p => p.Id == itemid); |
||||||
|
|
||||||
|
return item == null ? null : (decimal?)item.Price; |
||||||
|
} |
||||||
|
|
||||||
|
private class Item |
||||||
|
{ |
||||||
|
public int Id { get; set; } |
||||||
|
public decimal Price { get; set; } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal abstract class VMState |
||||||
|
{ |
||||||
|
protected VendingMachine _vendingMachine; |
||||||
|
public abstract void AddMoney(decimal money); |
||||||
|
public abstract void SelectItem(int itemId); |
||||||
|
public abstract void ReturnChange(decimal money); |
||||||
|
} |
||||||
|
|
||||||
|
internal class ReadyState : VMState |
||||||
|
{ |
||||||
|
public ReadyState(VendingMachine context) |
||||||
|
{ |
||||||
|
_vendingMachine = context; |
||||||
|
} |
||||||
|
|
||||||
|
public override void AddMoney(decimal money) |
||||||
|
{ |
||||||
|
_vendingMachine.State = _vendingMachine.HasMoneyState; |
||||||
|
_vendingMachine.State.AddMoney(money); |
||||||
|
} |
||||||
|
|
||||||
|
public override void ReturnChange(decimal money) |
||||||
|
{ |
||||||
|
throw new InvalidOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
public override void SelectItem(int itemId) |
||||||
|
{ |
||||||
|
throw new InvalidOperationException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal class HasMoneyState : VMState |
||||||
|
{ |
||||||
|
public HasMoneyState(VendingMachine context) |
||||||
|
{ |
||||||
|
_vendingMachine = context; |
||||||
|
} |
||||||
|
|
||||||
|
public override void AddMoney(decimal money) |
||||||
|
{ |
||||||
|
_vendingMachine.Money += money; |
||||||
|
Console.WriteLine($"Add {money}, Balance: {_vendingMachine.Money}"); |
||||||
|
} |
||||||
|
|
||||||
|
public override void ReturnChange(decimal money) |
||||||
|
{ |
||||||
|
_vendingMachine.State = _vendingMachine.DispenseChangeState; |
||||||
|
_vendingMachine.State.ReturnChange(_vendingMachine.Money); |
||||||
|
} |
||||||
|
|
||||||
|
public override void SelectItem(int itemId) |
||||||
|
{ |
||||||
|
decimal? price = _vendingMachine.GetPrice(itemId).Value; |
||||||
|
if (!price.HasValue) |
||||||
|
{ |
||||||
|
Console.WriteLine($"{itemId} not found"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (_vendingMachine.Money < price.Value) |
||||||
|
{ |
||||||
|
Console.WriteLine("Insufficient money"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
_vendingMachine.State = _vendingMachine.DispenseItemState; |
||||||
|
_vendingMachine.State.SelectItem(itemId); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal class DispenseItemState : VMState |
||||||
|
{ |
||||||
|
public DispenseItemState(VendingMachine context) |
||||||
|
{ |
||||||
|
_vendingMachine = context; |
||||||
|
} |
||||||
|
|
||||||
|
public override void AddMoney(decimal money) |
||||||
|
{ |
||||||
|
throw new InvalidOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
public override void ReturnChange(decimal money) |
||||||
|
{ |
||||||
|
throw new InvalidOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
public override void SelectItem(int itemId) |
||||||
|
{ |
||||||
|
decimal? price = _vendingMachine.GetPrice(itemId).Value; |
||||||
|
|
||||||
|
Console.WriteLine($"Dispense item#{itemId} ({price.Value})"); |
||||||
|
_vendingMachine.Money -= price.Value; |
||||||
|
|
||||||
|
_vendingMachine.State = _vendingMachine.DispenseChangeState; |
||||||
|
_vendingMachine.State.ReturnChange(_vendingMachine.Money); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
internal class DispenseChangeState : VMState |
||||||
|
{ |
||||||
|
public DispenseChangeState(VendingMachine context) |
||||||
|
{ |
||||||
|
_vendingMachine = context; |
||||||
|
} |
||||||
|
|
||||||
|
public override void AddMoney(decimal money) |
||||||
|
{ |
||||||
|
throw new InvalidOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
public override void ReturnChange(decimal money) |
||||||
|
{ |
||||||
|
if (_vendingMachine.Money > 0) |
||||||
|
{ |
||||||
|
Console.WriteLine($"Return change {money}..."); |
||||||
|
_vendingMachine.Money -= money; |
||||||
|
} |
||||||
|
|
||||||
|
_vendingMachine.State = _vendingMachine.ReadyState; |
||||||
|
} |
||||||
|
|
||||||
|
public override void SelectItem(int itemId) |
||||||
|
{ |
||||||
|
throw new InvalidOperationException(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue