state machine

main
syneffort 1 year ago
parent 7cce2e2d34
commit ebf7cddb25
  1. 236
      DesignPattern/DesignPattern/Patterns/StateMachine.cs
  2. 4
      DesignPattern/DesignPattern/Program.cs

@ -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();
}
}
}

@ -8,6 +8,8 @@ class Program
{
// FactoryClient.Work();
CommandClient.Work();
// CommandClient.Work();
StateMachinePattern.Work();
}
}

Loading…
Cancel
Save