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