4
\$\begingroup\$

I'm learning Factory pattern and I've implemented this simple example of an abstract factory. I've followed this video a little bit while writing this small example. Is there anything anti-pattern or wrong in this example?

I've created two different Pizzas

public interface IPizza
{
    public string Name { get; set; }
}

public class NewYorkPizza : IPizza
{
    public string Name { get; set; } = "NewYork Pizza";
}

public class ItalianPizza : IPizza
{
    public string Name { get; set; } = "Italian Pizza";
}  

Then relevant Pizza factories

public interface IPizzaFactory
{
    IPizza Create();
}

public class NewYorkPizzaFactory : IPizzaFactory
{
    public IPizza Create()
    {
        return new NewYorkPizza();
    }
}

public class ItalianPizzaFactory : IPizzaFactory
{
    public IPizza Create()
    {
        return new ItalianPizza();
    }
}  

Then created an abstract factory

public interface IAbstractPizzaFactory
{
    IPizzaFactory GetNewYorkPizzaFactory();
    IPizzaFactory GetItalianPizzaFactory();
}

public class AbstractPizzaFactory : IAbstractPizzaFactory
{
    public IPizzaFactory GetNewYorkPizzaFactory()
    {
        return new NewYorkPizzaFactory();
    }

    public IPizzaFactory GetItalianPizzaFactory()
    {
        return new NewYorkPizzaFactory();
    }
}  

Notice that I'm avoiding abstract class way and using only Interface to achieve kind of same thing and although, it looks correct to me, but I'm confuse here if it's the right approach or not?

And then I can use it like this

public class Test
{
    private readonly IAbstractPizzaFactory _abstractPizzaFactory;

    public Test(IAbstractPizzaFactory abstractPizzaFactory)
    {
        _abstractPizzaFactory = abstractPizzaFactory;
    }

    private void CreatePizza()
    {
        IPizza newYorkPizza = _abstractPizzaFactory.GetNewYorkPizzaFactory().Create();
        Console.WriteLine(newYorkPizza.Name);

        IPizza italianPizza = _abstractPizzaFactory.GetItalianPizzaFactory().Create();
        Console.WriteLine(italianPizza.Name);
    }

}
\$\endgroup\$
1

2 Answers 2

1
\$\begingroup\$

The main idea behind abstract factory is that you have multiple different products (sometimes referred as product family) and multiple different factories and you want to centralise the common theme without relying on concrete products.

Your example tries to implement the abstract factory and factory method patterns at the same time in a strange way. The factory method tries to hide the creation process of a single product. (Only at run-time you get the information to know which concrete type you need.)

I would suggest to read this SO topic thoroughly and choose the appropriate pattern for your needs.

\$\endgroup\$
0
\$\begingroup\$

[As @slepic pointed out in the comments, abstract factory with only one creational method may not be considered a real abstract factory. If you only need to create instances of one type, use factory method instead]

You slightly misunderstood the idea here: enter image description here Abstract factory is (as the name suggests) just a factory which is abstract, meaning that it lacks a concrete implementation. Abstract pizza factory doesn't produce pizza factories (it's not a factory of factories), it is a pizza factory.

You can look at a good example here and read more here.


Unrelated to the main question but also important: you made IPizza an interface but abstract class would fit this case better since it defines the identity of the class: you won't be able to define fields or constructors in an interface.

\$\endgroup\$
14
  • \$\begingroup\$ Hey, thanks for the reply. I've two questions then; IPizzaFactory is my abstract factory and now i need to use it somewhere. Because IPizzaFactory have two different implementations NewYorkPizzaFactory and ItalianPizzaFactory. I can constructor inject it using Func to get a specific factory I want. But then what's the difference? I mean to get a specific factory I'll have to use some kind of Enum or String. Are we really supposed to do it like that? I created IAbstractPizzaFactory to get rid of this problem basically... \$\endgroup\$
    – Hammas
    Oct 22, 2022 at 17:12
  • \$\begingroup\$ 2: Yes, I made IPizza an interface instead of making it an abstract class. Is it not okay if I don't have fields or constructor usage...? both implementations can have their own relevant fields or methods. \$\endgroup\$
    – Hammas
    Oct 22, 2022 at 17:15
  • \$\begingroup\$ @RaoArman why do you need an Enum or String for that? And why do you need Func? IAbstractPizzaFactory lists every possible factory which is against open-closed principle so I don't see what problem it helps to get rid of. \$\endgroup\$ Oct 22, 2022 at 17:33
  • 1
    \$\begingroup\$ @slepic if you only need one method, you don't need to create a factory interface and separate classes for each factory. Since OP only implemented creation of one object, this whole logic can indeed be turned into a factory method, but they decided not to. The other answer sums it up very well. \$\endgroup\$ Oct 25, 2022 at 12:14
  • 1
    \$\begingroup\$ @QuasiStellar That's right. I have already upvoted the other answer, but yours is totally misleading, sorry. \$\endgroup\$
    – slepic
    Oct 25, 2022 at 12:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.