0

first, sorry for my bad English. I'm learning some design patterns. I try to implement a factory in an example-code. This is the Code.

Program.cs:

namespace Factorymethod_self
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Animal myDog = new Dogs().SummonAnimal();
            myDog.Name = "Rex";
            myDog.Run(); // Isn't working
            myDog.Bark(); // Isn't working
            myDog.Pet(); // Isn't working
        }
    }
}

Animal.cs:

namespace Factorymethod_self
{
    public class Animal
    {
        private string name;

        public string Name
        {
            get => name;
            set => name = value;
        }
    }
}

Mammal.cs:

using System;

namespace Factorymethod_self
{
    public class Mammal : Animal
    {
        public void Run() => Console.WriteLine(Name + " is running");
    }
}

Bird.cs:

using System;

namespace Factorymethod_self
{
    public class Bird : Animal
    {
        public void Fly() => Console.WriteLine(Name + " is flying");
    }
}

GeneralFactory.cs:

using System;

namespace Factorymethod_self
{
    public abstract class GeneralFactory
    {
        public abstract Animal SummonAnimal();

        public void Pet()
        {
            Console.WriteLine("You petted " + SummonAnimal().Name);
        }
    }
}

Dogs.cs:

using System;

namespace Factorymethod_self
{
    internal class Dogs : GeneralFactory
    {
        public void Bark() => Console.WriteLine("The Dog is barking");

        public override Animal SummonAnimal()
        {
            Animal animal = new Mammal();
            return animal;
        }
    }
}

I think, the method Bark() isn‘t accessible, because Animal myDog = new Dogs().SummonAnimal(); doesn’t impellent the class Dogs() but Mammal(). But I Doesn’t understand, why the methods Run() and Pet() aren’t accessible. If I use GeneralFactory myDog = new Dogs();, I can access the Method Pet() but I don’t think, this is how the Factory should work. I’ve added a map for the classes

So, there are my questions.

What am I doing wrong here? How can I try to solve it? Is this even a right factory?

Thank you very much.

Jaro826
  • 13
  • 2
  • What you're missing is "casting". `Animal myDog` doesn't allow you to access dog methods because you're using the parent abstract type Animal. What you need to do is to cast it back to dog: `((Dog)myDog).Bark()` or just use the concrete type Dog instead of Animal: `Dog myDog =...` – Bizhan Jan 08 '22 at 13:11
  • Is that a typo or your `Dogs` factory is barking? – Eldar Jan 08 '22 at 13:14
  • By the way, this is not resembling factory pattern. – Bizhan Jan 08 '22 at 13:14
  • Thank you everybody, @Bizhan when I use `Dogs` then i don't need `SummonAnimal()`. Also `Name` and `Run()` still aren't accessable. @Eldar It's actually the factory. @Bizhan where is the wrong part of it? Or is there everythink wrong? ^^. – Jaro826 Jan 08 '22 at 13:20
  • @Bizhan I've tryed to cast `myDog`. Unfortunately it doesn't work either. But thank you anyway. – Jaro826 Jan 08 '22 at 15:38
  • After further research, I came up with a new question about this. Am I allowed to use own methods like `Bark()` or `Run()` or `Pet()` in `Dogs.cs`, `Mammal.cs` or `GeneralFactory.cs`, when they are not defined in `Animal`? Then the factory would just replace a simple switch statement. I mean, what if `Bird.cs` need more Methods than are definded in `Animal`? So it won't be flexible at all. – Jaro826 Jan 08 '22 at 21:38
  • You cannot access any of these method because your factory is creating instances of `Animal`, and in `Animal` you only declared nothing but the `Name` getter. Given that the client (the program that will use the factory) is aware of the kind of animal it needs, I believe that a better approach would be to have a factory method for each kind of animal (even if they share the `Animal` parent class) – perepm Jan 09 '22 at 12:23
  • @perepm Thank you, so at the `AbstractFactory (GeneralFactory.cs)` class I have to include the only the `SummonAnimal()` method? Or shouldn't `GeneralFactrory.cs` exist at all? [According to this Site](https://refactoring.guru/design-patterns/factory-method/#pseudocode), there is a abstract class for the Buttons. There is event a Method included. – Jaro826 Jan 09 '22 at 19:34
  • You've created an animal (dog) which is not inheriting any animal, but it's inheriting a factory. "Dog is not a factory!" – Bizhan Jan 10 '22 at 08:26
  • Also you've added a method bark to the factory. "factories don't bark!" – Bizhan Jan 10 '22 at 08:27
  • It is a fundamental part of object oriented design to model your domain properly. – Bizhan Jan 10 '22 at 08:53
  • I agree with @Bizhan, and also I'd recommend sticking to the naming conventions of the design patterns. The convention around factories is that the factory method it's called `makeXXX()`. This way your peers are able to identify the intent behind the code much faster. `summonAnimal()` could be anything, `makeAnimal` it's another thing :) – perepm Jan 10 '22 at 09:36
  • Moreover, your factory should define a method for each animal. My C# it's quite rusty, but IMO `AbstractFactory` should define `makeDog`, `makeBird`, etc... Then, your `ConcreteFactory` would implement those methods returning actual instances of `Dog`, `Bird`, etc... Lastly, and somewhat not really related to the factory pattern, the `Animal` interface only makes sense if `Dog`, `Bird` and `Fish` share behavior, and only if you need to hide that a Dog it's a `Dog`, a bird it's a `Bird`, so on and so forth – perepm Jan 10 '22 at 09:40
  • 1
    Take a look at this question, I'm sure it'll help: https://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns-in-javas-core-libraries/2707195#2707195 – perepm Jan 10 '22 at 09:41
  • Thank you all again. I think I'm starting to understand. "... the Animal interface only makes sense if Dog, Bird and Fish share behavior ..." -> If i want to use a Method in my Program, I have to declare it at the product-interface-class. "AbstractFactory should define makeDog, makeBird, etc..." -> Maybe I don't know it corect, but IMHO it's more like the simple factory :). @perepm – Jaro826 Jan 10 '22 at 16:38
  • 1
    "I'm sure it'll help: stackoverflow.com/questions/1673841/…" -> So at the factory-interface-class I just have to include the factory method `MakeAnimal`. Other Methods at the factory-interface i just create for using them at the factory-classes, not at the Program.cs. So I have to implement it like it: ` IAnimal myDog = new DogFactory().MakeAnimal();`. @perepm – Jaro826 Jan 10 '22 at 16:39

0 Answers0