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);
}
}
-
\$\begingroup\$ The Factory chapter from Head First Design Patterns. \$\endgroup\$radarbob– radarbob2022年10月23日 02:22:30 +00:00Commented Oct 23, 2022 at 2:22
2 Answers 2
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.
[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.
-
\$\begingroup\$ Hey, thanks for the reply. I've two questions then;
IPizzaFactory
is my abstract factory and now i need to use it somewhere. BecauseIPizzaFactory
have two different implementationsNewYorkPizzaFactory
andItalianPizzaFactory
. I can constructor inject it usingFunc
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 ofEnum
orString
. Are we really supposed to do it like that? I createdIAbstractPizzaFactory
to get rid of this problem basically... \$\endgroup\$Hammas– Hammas2022年10月22日 17:12:46 +00:00Commented Oct 22, 2022 at 17:12 -
\$\begingroup\$ 2: Yes, I made
IPizza
an interface instead of making it anabstract
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– Hammas2022年10月22日 17:15:49 +00:00Commented Oct 22, 2022 at 17:15 -
\$\begingroup\$ @RaoArman why do you need an
Enum
orString
for that? And why do you needFunc
?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\$QuasiStellar– QuasiStellar2022年10月22日 17:33:56 +00:00Commented 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\$QuasiStellar– QuasiStellar2022年10月25日 12:14:20 +00:00Commented 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– slepic2022年10月25日 12:38:35 +00:00Commented Oct 25, 2022 at 12:38
Explore related questions
See similar questions with these tags.