Reputation: 155
Help me figure out the State pattern. There is a task - to write a program that simulates turning on and off the PC. I was prompted to use the State pattern. But I'm not sure that I use it correctly. My turn pc model has things in common with a real one, but certainly not for sure. Therefore, I divided the boot process into several stages - turning on the computer, boot loaders 1-3 level and loading the kernel os. Program structure.
At each stage, their actions are performed, in addition to implementing the methods of the implemented interface. In the implementation of the interface methods, I assign a new object to the state of the pc. I do this because I saw a similar action in the example. But I don’t understand how to use it later.
Interface:
internal interface IPCState
{
bool TurnON(Computer computer);
bool TurnOff(Computer computer);
}
An example implementation of the method in one of the stages:
// Level 1 bootloader.Master boot record
internal class LoaderOfTheFirstLevel : IPCState
{
public bool TurnOff(Computer computer)
{
throw new NotImplementedException();
}
public bool TurnON(Computer computer)
{
// If the self-testing stage has been successfully completed, this means that the processes of the first stage are completed successfully we move on
if (POST())
{
computer.State = new LoaderOfTheSecondLevel();
return true;
}
return false;
}
// Self-test: we check hardware failures, one signal after POST signals that everything is in order.
private bool POST() => true;
}
In the main method, I call the instance constructor of each stage and put the result in a list. And if at the end all the stages worked without errors - the PC is started and ready for use. Thanks in advance.
Main:
static void Main()
{
List<bool> operationRes = new List<bool>();
PowerSocket.SetElectricityState(true);
Computer computer = new Computer(new SystemStartup());
operationRes.Add(computer.TurnOn());
computer = new Computer(new LoaderOfTheFirstLevel());
operationRes.Add(computer.TurnOn());
computer = new Computer(new LoaderOfTheSecondLevel(operationRes.Last()));
operationRes.Add(computer.TurnOn());
computer = new Computer(new LoaderOfTheThirdLevel(operationRes.Last()));
operationRes.Add(computer.TurnOn());
computer = new Computer(new BootLoaderOSKernel(operationRes.Last()));
operationRes.Add(computer.TurnOn());
if (operationRes.All(r => r))
{
Console.WriteLine("OS is ready to work");
}
else
{
Console.WriteLine("Error");
}
Console.ReadLine();
}
Can someone explain what i did wrong?
Upvotes: 1
Views: 200
Reputation: 7746
Currently, your IPCState methods accept a Computer. Instead, the Computer should have a state. Also, states should return states; that's what a state machine does: takes a state, given some input, returns a state.
Here, the client asks the Computer to boot(). The Computer starts off by POSTing then loads the boot device, transfers to the bootloader, which then transfers to the kernel. The kernel never returns. If it does, panic.
using System;
public interface IComputerState
{
IComputerState load();
}
public class PanicState : IComputerState {
public IComputerState load() {
Console.WriteLine("Kernel panic!");
System.Threading.Thread.Sleep(500);
return new PanicState();
}
}
public class KERNEL : IComputerState {
public IComputerState load() {
Console.WriteLine("Kernel started...");
return new PanicState();
}
}
public class BOOTLOADER : IComputerState {
public IComputerState load() {
Console.WriteLine("Bootloader started...");
Console.WriteLine("Changing memory model...");
Console.WriteLine("In long-mode...");
return new KERNEL();
}
}
public class LOAD_MBR : IComputerState {
public IComputerState load() {
Console.WriteLine("Found boot device...");
Console.WriteLine("Loading boot device...");
return new BOOTLOADER();
}
}
public class POST : IComputerState {
public IComputerState load() {
Console.WriteLine("POST...");
return new LOAD_MBR();
}
}
public class Computer
{
IComputerState state;
public Computer() {
state = new POST();
}
public void boot()
{
Console.WriteLine("booting...");
while (true) {
state = state.load();
System.Threading.Thread.Sleep(200);
}
}
}
public class Program
{
public static void Main()
{
Computer c = new Computer();
c.boot();
}
}
booting...
POST...
Found boot device...
Loading boot device...
Bootloader started...
Changing memory model...
In long-mode...
Kernel started...
Kernel panic!
Kernel panic!
Kernel panic!
Upvotes: 3