Konsolowe menu - co robię źle? (Factory pattern)

1

Witam,

Chciałem w końcu, aby kod który tworzę nadawał się do czegokolwiek. Więc chciałem zacząć od poprawienia swoich podstaw. Tak więc otworzyłem książkę z zadaniami, pierwsze polega na zwróceniu pola prostokąta. Samo zwrócenie jest trywialne, ale nagle mnie natchnęło - chcę napisać jeden program, gdzie każde kolejne zadanie będzie oddzielną klasą.

I tutaj się zaczęło. Rozpocząłem oczywiście od napisania metody DisplayMenu

        private static int DisplayMenu()
        {
            Console.WriteLine("Hello :)");
            Console.WriteLine("1. Zadanie nr. 1");
            Console.WriteLine("2. Zadanie nr. 2");
            Console.WriteLine("3. Zadanie nr. 3");
            Console.WriteLine("4. Exit");
            Console.WriteLine("Wybierz zadanie:");
            
            var input = Console.ReadLine();
            int.TryParse(input, out var result);
            return result;
        }

I w mainie oczywiście pętlę do while

            int option;
            do
            {
                option = DisplayMenu();
            } while (option!=4);

Dalej myślę, hmmmm raczej nie będę tutaj pisał if option = 1, create new class.... ponieważ metoda main skończy się molochem na 1000 linijek. Przypomniało mi się zasłyszane, że ify powinny zostać w czeluściach fabryk. Więc pierwsze co robię to yt + factory pattern. Brzmi ciekawie, można w nim powoływać do życia obiekty, więc zabieram się za implementację. Tworzę kolejno interface IExercise i implementuję go w klasie Exercise1.

No dobrze, mam klasę z pierwszym zadaniem, ale potrzebuję jeszcze fabryki. Więc szybki interface fabryki:

    public interface IExerciseProvider
    {
        IExercise Provide(int option);
    }

Oraz sama fabryka

   public class ExerciseProvider : IExerciseProvider
   {
       public IExercise Provide(int option)
       {
           if (option == 1)
           {
               return new Exercise1();
           }

           return null;
       }
   }

Pewnie domyślnie nie chcę zwracać nulla, na razie zostawiam to na przyszłość. Dalej już zaczynają się schody. Aby w mojej metodzie main można było cokolwiek zrobić trzeba powołać do życia fabrykę. Więc szybkie

           Console.WriteLine("Pole wynosi: " + RactangleField());
           var exercise = provider.Provide(option);

Myślę eureka - inicjuje fabrykę, daje jej numer zadania i właśnie mam powołany do życia obiekt który chcę. Dopisuję na szybko metodę w ćwiczeniu 1 do obliczania pola prostokąta

public double RactangleField(double a, double b)
        {
            return a * b;
        }

I moje zdziwienie, mimo stworzonego obiektu, nie mam możliwości wywołania jego metody. Trochę logiczne, w kolejnej klasie będę miał inną - a skąd wiadomo co mam konkretnie na myśli. Dopisuje więc do IExercise metodę create która inicjuje co ma dana klasa robić, mogę ją później wywołać, wszystko działa... ale w końcu nie wiem czy to to. Wydaje mi się że zrobiłem błąd ale nie wiem gdzie. Dla rozjaśnienia jak wygląda mój program poniżej całościowy kod konkretnych klas:

Program.cs

class Program
    {
        private static int DisplayMenu()
        {
            Console.WriteLine("Hello :)");
            Console.WriteLine("1. Zadanie nr. 1");
            Console.WriteLine("2. Zadanie nr. 2");
            Console.WriteLine("3. Zadanie nr. 3");
            Console.WriteLine("4. Exit");
            Console.WriteLine("Wybierz zadanie:");
            
            var input = Console.ReadLine();
            int.TryParse(input, out var result);
            return result;
        }
        
        static void Main(string[] args)
        {
            int option;
            do
            {
                option = DisplayMenu();
                ExerciseProvider provider = new ExerciseProvider();
                var exercise = provider.Provide(option);
                exercise.Create();

            } while (option!=4);
            Console.WriteLine(option);
        }
    }

IExercise.cs

public interface IExercise
    {
        void Create();
    }

Exercise1.cs

public class Exercise1 : IExercise
    {
        private double _a;
        private double _b;
        public double RactangleField(double a, double b)
        {
            return a * b;
        }

        public void subMenu()
        {
            Console.WriteLine("Podaj liczbę a");
            var input1 = Console.ReadLine();
            double.TryParse(input1, out var a);
            Console.WriteLine("Podaj liczbę b");
            var input2 = Console.ReadLine();
            double.TryParse(input2, out var b);

            _a = a;
            _b = b;
        }
        public void Create()
        {
           subMenu();
           Console.WriteLine("Pole wynosi: " + RactangleField(_a,_b));
           Console.ReadKey();
        }
    }

IExerciseProvider.cs

public interface IExerciseProvider
    {
        IExercise Provide(int option);
    }

ExerciseProvider.cs

public class ExerciseProvider : IExerciseProvider
    {
        public IExercise Provide(int option)
        {
            if (option == 1)
            {
                return new Exercise1();
            }

            return null;
        }
    }
1

HIHIHI :J :J :J :) :))) Też zaczynałem od pisania Malware czyli programu złośliwego (który złośliwie nie chce działać). :D :D :D :D

Zrób sobie pyłki w słowniku, albo maszynę stanów. :> :> :D W tym wypadku sprawdzenie nulla to zwykła walidacja :J :J punktu wejścia :D, więc do fabryki to nie pasuje. :P :P :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1