Design ATM Machine with state design pattern [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
recently I've come across a question which is Design an ATM Machine using State Design Pattern an I'm new to design patterns but somehow I've completed the question and designed an ATM Machine using state design pattern in c#.
So, I just want to kindly tell me is there any optimization that can be done on this program, or this solution can be accepted. The current solution is running without any error.
Client Class which controls the state of ATM Machine.
public class Client
{
public static void Main(string [] args)
{
AtmMachine atmMachine = new AtmMachine();
atmMachine.enterPinAndWithdrawMoney();
atmMachine.ejectDebitCard();
atmMachine.insertDebitCardState();
atmMachine.enterPinAndWithdrawMoney();
atmMachine.insertDebitCardState();
atmMachine.ejectDebitCard();
Console.ReadLine();
}
}
ATM Machine Class
public class AtmMachine : IAtmMachineState
{
private IAtmMachineState _state;
public int _balance = 5000;
public int _pin = 1234;
public AtmMachine()
{
_state = new NoDebitCardState();
}
public IAtmMachineState GetMachineState()
{
return _state;
}
public void setAtmMachineState(IAtmMachineState state)
{
this._state = state;
}
public void ejectDebitCard()
{
_state.ejectDebitCard();
if(_state is HasDebitCardState)
{
_state = new NoDebitCardState();
Console.WriteLine("State Changed");
Console.WriteLine(_state.GetType().Name);
}
}
public void enterPinAndWithdrawMoney()
{
if(_state is HasDebitCardState)
{
_state.enterPinAndWithdrawMoney();
}
}
public void insertDebitCardState()
{
if(_state is NoDebitCardState)
{
_state = new HasDebitCardState();
Console.WriteLine("State Changed");
Console.WriteLine(_state.GetType().Name);
}
}
}
ATM Machine Interface
public interface IAtmMachineState
{
void insertDebitCardState();
void ejectDebitCard();
void enterPinAndWithdrawMoney();
}
Has Debit Card State
class HasDebitCardState : IAtmMachineState
{
AtmMachine atmMachine;
public HasDebitCardState()
{
atmMachine = new AtmMachine();
}
public void ejectDebitCard()
{
Console.WriteLine("Debit card ejected successfully");
}
public void enterPinAndWithdrawMoney()
{
Console.WriteLine("Enter the Pin:");
int pin = int.Parse(Console.ReadLine());
if(atmMachine._pin==pin)
{
Console.WriteLine("Enter the amount");
int amount = int.Parse(Console.ReadLine());
if(amount > atmMachine._balance)
{
Console.WriteLine("Money can not be withdrawn because of low balance");
}
else
{
atmMachine._balance = atmMachine._balance - amount;
Console.WriteLine("Please collect your cash");
Console.WriteLine("Remaining Balance {0}", atmMachine._balance);
}
} else
{
Console.WriteLine("Incorrect Pin.");
}
}
public void insertDebitCardState()
{
Console.WriteLine("Debit card is already there, so can not insert debit card");
}
}
No Debit Card State
class NoDebitCardState : IAtmMachineState
{
public void ejectDebitCard()
{
Console.WriteLine("No debit card inside atm");
}
public void enterPinAndWithdrawMoney()
{
Console.WriteLine("No debit card in ATM Machine, so you can not withdraw money");
}
public void insertDebitCardState()
{
Console.WriteLine("Debit Card Inserted");
}
}

You might want to consider using an abstract class instead of an interface.
Instead of an abstract class you could also used default implementations but this will limit you in using pre defined members and state as in your abstract class.
This way you can have some standard functionality and avoid re writing the same code multiple times.
Override only the functionality that changes per state.
You can also easily extend by calling the base implementation of the abstract class as well as the extra logic in each state.

Related

How to save the state of an object in windows forms [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
Cant change a field value permanently in my windows forms app.
Forgive me if this is something answered somewhere else. I did look and didn't find anything specific. I am trying to design a small game in a windows form app. However an issue I am having is when I change the value of a field in a button event it doesn't permanently apply the change. So when i click on the button again it does not reduce monster hp to 8 it simply repeats the code as if it was the first time executing it. Iv tried using static and ref variables but perhaps I am using them wrong.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void PlayerHealth_Click(object sender, EventArgs e)
{
}
public void MonsterHealth_Click(object sender, EventArgs e)
{
}
private void AttackBtn_Click(object sender, EventArgs e)
{
Player player = new Player();
Monster monster = new Monster();
player.AttackMonster(player, monster);
MonsterHealth.Text = monster.HP.ToString();
}
}
public class Player
{
public int HP { get; set; }
public int Attack = 1;
public void AttackMonster(Player player, Monster monster)
{
monster.HP -= player.Attack;
}
}
public class Monster
{
public int HP = 10;
public int Attack { get; set; }
}
}
I am aiming to get the HP field to reduce by one each time the button is clicked. This is not whats happens as of now.
HP variable is not decrementing, because you are creating new instance of Monster class in every AttackBtn_Click ().
To avoid it create a class level property of Monster instance and instantiate it at class level and use it in AttackBtn_Click()function
public partial class Form1 : Form
{
public Monster MonsterInstance { get; private set; } = new Monster();
public Player PlayerInstance { get; private set; } = new Player();
public Form1()
{
InitializeComponent();
}
//Your business logic
private void AttackBtn_Click(object sender, EventArgs e)
{
PlayerInstance.AttackMonster(PlayerInstance, MonsterInstance);
MonsterHealth.Text = MonsterInstance.HP.ToString();
}
}

Call ALL children methods of a class from another class [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
Lets say that i have a "Timer" class with a method that every 1 second is called, and it calls another method in the class "Gear":
public class Timer
{
public void OnTick()
{
Gear.Update();
}
}
public class Gear
{
public static void Update() { }
}
This kinda works, but it's only called on the base class.
The method "Update" should be called in all the childrens of "Gear":
e.g:
public class AnotherClass : Gear
{
public override void Update() { // do stuff }
}
public class YetAnotherClass : Gear
{
public override void Update() { // do stuff }
}
public class AndAnotherClass : Gear
{
public override void Update() { // do stuff }
}
How can i do this?
In order for the code to work the way you want, you'd need to do something like this (I would worry about a memory leak):
public abstract class Gear
{
readonly static List<Gear> gears = new List<Gear>();
public Gear()
{
gears.Add(this);
}
public static void Update()
{
foreach (var gear in gears)
gear._Update();
}
protected abstract void _Update();
}
public sealed class Gear1 : Gear
{
protected override void _Update()
{
//do stuff
}
}
public sealed class Gear2 : Gear
{
protected override void _Update()
{
//do stuff
}
}
public sealed class Gear3 : Gear
{
protected override void _Update()
{
//do stuff
}
}
public static void Main(string[] args)
{
var timer =
new Timer(o => Gear.Update(), null, 0, SOME_INTERVAL);
}
However, you might be better off by defining the base case thusly:
public abstract class Gear
{
public abstract void Update();
}
And then define a collection class:
public sealed class GearCollection : List<Gear>
{
public void Update()
{
foreach (var gear in this)
gear.Update();
}
}
And then
public static void Main(string[] args)
{
var gears = new GearCollection();
//add gear instancs to gears
var timer = new Timer(o => gears.Update(), null, 0, SOME_INTERVAL);
}

How to call a function only, when in a specific case in a switch case for unit test?

So I have a class Doorcontrol that can have 4 states
public enum DoorControlState
{
DoorClosed,
DoorOpening,
DoorOpen,
DoorBreached
}
To open the door an accescode is needed, the code is then validated and if it's correct the door is opened. If the door is not in the Closed state nothing should happen. It should go like this RequestEntry(id)[Doorcontrol]->ValidateEntryRequest(id)[IUserValidation]->OK[Doorcontrol]->Open[IDoor]->change state to DoorOpening. Idoor then calls DoorOpen and the state changes to DoorOpen and so on.
I have implemented the DoorControl class as follows
public class DoorControl
{
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
private int _id;
public DoorControl(IDoor door, IEntryNotification entryNotification, IUserValidation userValidation, DoorControlState doorControlState)
{
_door = door;
_entryNotification = entryNotification;
_userValidation = userValidation;
_doorControlState = doorControlState;
}
public void Run()
{
switch (_doorControlState)
{
case DoorControlState.DoorClosed:
bool foo = RequestEntryId();
if (foo)
{
_door.Open();
_doorControlState = DoorControlState.DoorOpening;
}
break;
case DoorControlState.DoorOpening:
_door.Close();
_doorControlState = DoorControlState.DoorOpen;
break;
case DoorControlState.DoorOpen:
// Do stuff....
break;
case DoorControlState.DoorBreached:
// Do stuff
break;
default:
throw new InvalidEnumArgumentException();
}
}
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
public void DoorOpened()
{
//
}
public void DoorClosed()
{
//
}
}
}
The UserValidation and Door classes are implemented as Interfaces
public interface IUserValidation
{
bool ValidateEnetryRequest();
}
public interface IDoor
{
void Open();
void Close();
}
I am testing my code using Nunit and NSubstitute
namespace DoorControl.Unit.Test
{
[TestFixture]
public class DoorControlUnitTest
{
private DoorControl _uut;
private IDoor _door;
private IEntryNotification _entryNotification;
private IUserValidation _userValidation;
private DoorControlState _doorControlState;
[SetUp]
public void SetUp()
{
_door = Substitute.For<IDoor>();
_entryNotification = Substitute.For<IEntryNotification>();
_userValidation = Substitute.For<IUserValidation>();
_doorControlState = DoorControlState.DoorClosed;
_uut = new DoorControl(_door, _entryNotification, _userValidation, _doorControlState);
}
[Test]
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.RequestEntryId(); // Can't called that cause it's private
_door.Received().Open();
}
}
}
I can't figure out how to make it call RequestEntryId only when it's in the Doorclosed state and ignore it if it's in another state.
Edit: What state the Doorcontrol is in should be hidden from everybody else.
public void InputCorrectId()
{
_userValidation.ValidateEnetryRequest().Returns(true);
if(_doorControlState == DoorControlState.DoorClosed){
_uut.RequestEntryId(); // Make it public
}
_door.Received().Open();
}
Or into the doorcontrol class like:
case DoorControlState.DoorClosed:
RequestEntryId();
I'm not sure exactly what you're asking: when you say "I can't figure out how to make it call RequestEntryId only when it's in the Doorclosed state and ignore it if it's in another state." do you mean the unit test? I can't figure out why you would want to do that. Please provide more info and I'll update this answer if I can help.
I did notice a couple of things that might help you though. First RequestEntryId has a problem:
private bool RequestEntryId()
{
bool maybeFoo = _userValidation.ValidateEnetryRequest();
if (maybeFoo = true)
{
return true;
}
return false;
}
Here maybeFoo = true is an assignment which overwrites the result of ValidateEntryRequest(). I think you intended a comparison with ==, but the whole method can be simplified to:
private bool RequestEntryId()
{
return _userValidation.ValidateEnetryRequest();
}
With that fixed we can run a few tests to check how the public Run method behaves. Given your SetUp creates a doorcontrol already in a Closed state, we can test that the door opens for valid users, and doesn't open for invalid users.
[Test]
public void ClosedDoorOpensWhenUserIsValid()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_door.Received().Open();
}
[Test]
public void ClosedDoorDoesNotOpenWhenUserInvalid()
{
_userValidation.ValidateEnetryRequest().Returns(false);
_uut.Run();
_door.DidNotReceive().Open();
}
We can also check the validation is not repeated for an already opened door:
[Test]
public void OpenDoorDoesNotRevalidate()
{
_userValidation.ValidateEnetryRequest().Returns(true);
_uut.Run();
_userValidation.ClearReceivedCalls();
_uut.Run();
_userValidation.DidNotReceive().ValidateEnetryRequest();
}
Hope this gives you some ideas for testing this.

Display sum and average of numbers 1 to 100 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am trying to write a simple program in C# to display the sum and the average of the numbers 1 to 100. the output should look like...
the sum is 5050
the average is 50.5
I cant seem to get it to work properly though, the return value only returns the sum not the wording before it, I have tried other ways for it to display the message and sum and ave but they arent working. I am trying to do this using the model view view controller method, but cant understand where I am going wrong and how to get it to display the above result. my code is below.
class SumAndAverage
{
public float sum = 0;
public float ave = 0;
public float SumAndAve()
{
for (int i = 1; i <= 100; i++)
{
sum = sum + i;
ave = sum / i;
}
return sum + ave;
}
}
}
class SumAndAverageController
{
IView view;
SumAndAverage sumAndAverage;
public SumAndAverageController(IView theView, SumAndAverage theSumAndAverage){
view = theView;
sumAndAverage = theSumAndAverage;
}
public void Go()
{
view.Start();
//mAndAverage.SetNumber(view.GetString("Please enter a number"));
view.Show(sumAndAverage.SumAndAve());
//view.Show(sumAndAverage.Result());
view.Stop();
}
}
class ConsoleView : IView
{
public void Start()
{
Console.Clear();
}
public void Stop()
{
Console.WriteLine("Press any key to continue");
Console.ReadKey();
}
public void Show<T>(T message)
{
Console.WriteLine(message);
}
}
interface IView
{
void Start();
void Stop();
void Show<T>(T message);
}
class Program
{
static void Main(string[] args)
{
new SumAndAverageController(new ConsoleView(), new SumAndAverage()).Go();
}
}
using System;
using System.Linq;
namespace SumAndAverage
{
class Program
{
static void Main(string[] args)
{
var data = Enumerable.Range(1, 100);
Console.WriteLine("the sum is " + data.Sum());
Console.WriteLine("the average is " + data.Average());
}
}
}

C# Class Library [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I want to develop a class library in C# whose methods I would call in a hierarchical way, like this:
using MyProduct.Common;
protected void Page_Load(object sender, EventArgs e)
{
Utils myUtils = new Utils();
int res = myUtils.Numbers.Add(1, 2);
string text = myUtils.Text.ToUpper("test"); //***
}
Is it possible to do, using Namespaces, classes, interfaces, whatever?
UPDATE:
I have my library like this, but it doesn't work, as I can't "reference a type through an expression" (line with *** above)
namespace MyProduct.Common
{
public class Utils
{
public static class Text
{
public static string ToUpper(string s)
{
return s.ToUpper();
}
}
}
}
UPDATE 2:
Ok, it seems I need to clarify...
I have this MyProduct.Common.dll:
namespace MyProduct.Common
{
public static class Utils
{
public static class Text
{
public static void ToUpper(string s)
{
return s.ToUpper();
}
}
public static class Number
{
public static void Add(int a, int b)
{
return (a + b);
}
}
}
}
and I have my project:
using MAD.Comum;
...
protected void Page_Load(object sender, EventArgs e)
{
string x = Utils.Text.ToUpper("aa"); //this works
string res = Utils.Number.Add(1, 2); //this works
}
and now 2 questions:
- is it possible to separate classes Number and Text in 2 files?
- is this a good design?
Of course, you can do something like this:
namespace MyProduct.Common.Utils
{
public static class Numbers
{
public static int Add(int n, int m)
{
return n + m;
}
}
public static class Text
{
public static string ToUpper(string str)
{
return str.ToUpper();
}
}
}
And you use it like this:
MyProduct.Common.Utils.Numbers.Add(1, 2);
Hope this helps.
Cheers

Categories