1

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?

2
  • Please post your code in text format, not image format. People who want to reproduce the issue need to be able to copy/paste your code. Commented Jul 3, 2020 at 19:24
  • @Flater did it. Commented Jul 3, 2020 at 19:27

1 Answer 1

3

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.

pc_boot

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!
Sign up to request clarification or add additional context in comments.

2 Comments

how can I change the code correctly so that the load() method of the KERNEL class returns true or new PanicState()(and in class PanicState method load() will return false), because if I understand correctly, this is the final step in loading the pc?
Since load() is the state transition function, we should not modify it. However, boot() would simply return a boolean once it enters the KERNEL or PANIC state. You can easily test the state instance in the while loop and act accordingly, i.e., if state instanceof KERNEL return true else if state instanceof PANIC return false

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.