C
C#13mo ago
Merineth

✅ Factory Method Pattern

Does someone have a good explanation or perhaps a link to somewhere where i can learn this? Been trying to find a video or similar but it just doesn't stick :(
81 Replies
Pobiega
Pobiega13mo ago
so you know how constructors work right?
Merineth
MerinethOP13mo ago
I think soooo
Pobiega
Pobiega13mo ago
var x = new Product("Apple", 15, 3.5); etc
Merineth
MerinethOP13mo ago
We store an instance of Product inside var x ?
Pobiega
Pobiega13mo ago
sure, but the "constructor" here is the new Product("Apple", 15, 3.5) part
Merineth
MerinethOP13mo ago
So the constructor is the one that instanciates the object?
Pobiega
Pobiega13mo ago
yes
Merineth
MerinethOP13mo ago
Oki, then yeah i'm with you :cathype:
Pobiega
Pobiega13mo ago
a "factory" in OOP is a class/method that knows how to create something else. it knows the details needed to call the constructor properly, and maybe set some values on the object before returning it in this case, maybe you dont know what the 15 and 3.5 should be lets assume 15 is the "Product ID", and that should be an incremeneted number. It would be silly to expect the programmer to constantly keep track of the current ID and manually give it
Merineth
MerinethOP13mo ago
Oki
Pobiega
Pobiega13mo ago
so we can make a "ProductFactory" instead that keeps track of it for us
Merineth
MerinethOP13mo ago
Would that be an abstract class/interface?
Pobiega
Pobiega13mo ago
uh... probably not
Merineth
MerinethOP13mo ago
Weird, i think our teacher specifies it as such 😭
Pobiega
Pobiega13mo ago
abstract things cant be created, so how would you create the factory? Ah, are you refering specifically to the "abstract factory" pattern?
Merineth
MerinethOP13mo ago
I think so? GoF ?
Merineth
MerinethOP13mo ago
No description
Pobiega
Pobiega13mo ago
yeah
Merineth
MerinethOP13mo ago
This is what she explains it as
Pobiega
Pobiega13mo ago
yeah GoF has an "abstract factory" in it FactoryBase here is your abstract factory check this out: https://refactoring.guru/design-patterns/abstract-factory
Merineth
MerinethOP13mo ago
How do you know that is abstract
Pobiega
Pobiega13mo ago
their explanations are usually pretty good well it has a Base suffix and the title is in italics and there are other classes called ConcreteSomething concrete is the opposite of abstract...
Merineth
MerinethOP13mo ago
Ooh
Merineth
MerinethOP13mo ago
No description
Merineth
MerinethOP13mo ago
So in my case the interface here would be Carfactory?
Pobiega
Pobiega13mo ago
? this is the first time you mention Car
Merineth
MerinethOP13mo ago
Oh wait i might not have included everything
Merineth
MerinethOP13mo ago
No description
Merineth
MerinethOP13mo ago
This is what i'm working on atm And i'm trying to implement the Factory method (which i'm currently learning)
Pobiega
Pobiega13mo ago
right In your case Car would be an abstract base class, not an interface, but otherwise it would fulfill the same role as "Chair" does in the above image
Merineth
MerinethOP13mo ago
I see
namespace Creational.FactoryMethodPattern.Cars
{
public abstract class Car
{
}
}
namespace Creational.FactoryMethodPattern.Cars
{
public abstract class Car
{
}
}
We were provided an abstract class for Car in the project Hmm i’ll finish reading the page, one moment ^^
MODiX
MODiX13mo ago
Merineth
Quoted by
<@577931037393420298> from #Factory Method Pattern (click here)
From Merineth
React with ❌ to remove this embed.
Merineth
MerinethOP13mo ago
Would the "Client" be my main method?
Pobiega
Pobiega13mo ago
yeah
Merineth
MerinethOP13mo ago
Client is missing in this? Would FactoryBase be a subclass interface of the client?
Pobiega
Pobiega13mo ago
you dont specifically need a client FactoryBase is AbstractFactory they do the same thing
Merineth
MerinethOP13mo ago
I see So this Interface would be called from main in order to make the car? And then depending on what type of car we want different Concrete Factories are called? 😭 this is so confusing I don't even see the benefit of using this Factory method Not even gpt can explain it to me :I
public static void Main(string[] args)
{
// How can we apply the Factory Method Design Pattern,
// so that we don't explicitly create the cars below
// using the new operator and a constructor call?

Car car;

car = new HyundaiCoupe();
Console.WriteLine($"Type: {car.GetType()}");

car = new HyundaiI30();
Console.WriteLine($"Type: {car.GetType()}");

car = new MazdaMX5();
Console.WriteLine($"Type: {car.GetType()}");

car = new Mazda6();
Console.WriteLine($"Type: {car.GetType()}");
}
public static void Main(string[] args)
{
// How can we apply the Factory Method Design Pattern,
// so that we don't explicitly create the cars below
// using the new operator and a constructor call?

Car car;

car = new HyundaiCoupe();
Console.WriteLine($"Type: {car.GetType()}");

car = new HyundaiI30();
Console.WriteLine($"Type: {car.GetType()}");

car = new MazdaMX5();
Console.WriteLine($"Type: {car.GetType()}");

car = new Mazda6();
Console.WriteLine($"Type: {car.GetType()}");
}
Pobiega
Pobiega13mo ago
Well in this case there is no benefit
Merineth
MerinethOP13mo ago
Like i fail to see what's wrong with this
Pobiega
Pobiega13mo ago
This is just a stupid example
Merineth
MerinethOP13mo ago
:( 10/10 teacher
Pobiega
Pobiega13mo ago
eh, more like bad... kursplaner
Merineth
MerinethOP13mo ago
(: yup
Pobiega
Pobiega13mo ago
its hard to understand why you'd need an abstract factory until you do
Merineth
MerinethOP13mo ago
So they dont want me to instanciate cars with constructors in the main program
Pobiega
Pobiega13mo ago
and its not a pattern you use for simple apps traditionally
Merineth
MerinethOP13mo ago
They want me to use a factory to do it for me So i instanciate them inside the factory instead
Pobiega
Pobiega13mo ago
I mean, the simplest implementation of a factory literally just calls the constructor... which is pretty silly
Merineth
MerinethOP13mo ago
Welp i've been trying to figure out what it even is for a few hours now I'm surprised there aren't videos covering it under 20 min
Pobiega
Pobiega13mo ago
the link I gave above is... pretty good.
Merineth
MerinethOP13mo ago
:{ Yeah for someone who already knows it 😭 The first thing the Abstract Factory pattern suggests is to explicitly declare interfaces for each distinct product of the product family So i create an interface for car? or rather an abstract class
Pobiega
Pobiega13mo ago
Well, you already have that, no?
Merineth
MerinethOP13mo ago
No description
Merineth
MerinethOP13mo ago
Would that be the FactoryBase? Or do i need another abstract class for a total of two?
Pobiega
Pobiega13mo ago
you would indeed have two one for Car, one for AbstractCarFactory or CarFactoryBase whatever then you make one concrete factory for each car variant
Merineth
MerinethOP13mo ago
Confusing considering there aren't two here
Pobiega
Pobiega13mo ago
you can make your factories in different ways that one has its example of the three kinds of furniture each factory knows how to make a chair, a sofa and a table the difference there is the style of the factory. In your case, you only have one "dimension" of difference
Merineth
MerinethOP13mo ago
So in the example from the site we'd need 3 interfaces for each chair, sofa and table?
Pobiega
Pobiega13mo ago
yeah a baseclass for each type either interface or abstract class
Merineth
MerinethOP13mo ago
Ok so why do iu need two interfaces when there is only one object, car (i just assume interface and abstract class are the same)
Pobiega
Pobiega13mo ago
because you have the BaseThing (car) and the FactoryBase thats two things but none are concrete
Merineth
MerinethOP13mo ago
And what's the difference between those two iabstract classes?
Pobiega
Pobiega13mo ago
what one is a car the other is a factory ... .d
Merineth
MerinethOP13mo ago
hahahah but i don't get it I don't even understand what they are mean to do
Pobiega
Pobiega13mo ago
in this case, NOTHING
Merineth
MerinethOP13mo ago
I have 4 different types of cars, Oh
Pobiega
Pobiega13mo ago
they are literally just to tie the hierarchies together
Merineth
MerinethOP13mo ago
I found the solution they provided As you said the Car abstract class is completely empty However the CarFactoryis not
using Creational.FactoryMethodPattern.Cars;

namespace Creational.FactoryMethodPattern.Factories
{
public abstract class CarFactory
{
public abstract Car CreateCar(string model);
}
}
using Creational.FactoryMethodPattern.Cars;

namespace Creational.FactoryMethodPattern.Factories
{
public abstract class CarFactory
{
public abstract Car CreateCar(string model);
}
}
Pobiega
Pobiega13mo ago
well, it provides the base implementation for CreateCar yeah however, no body so its effectively an interface
Merineth
MerinethOP13mo ago
no body?
Pobiega
Pobiega13mo ago
yeah no body notice how the method has... no body
Merineth
MerinethOP13mo ago
Oh, right iirc abstract classes can't have a body to their methods only the definitions
Pobiega
Pobiega13mo ago
abstract classes can abstract methods cant abstract classes can have non-abstract methods
Merineth
MerinethOP13mo ago
using Creational.FactoryMethodPattern.Cars;
using Creational.FactoryMethodPattern.Factories;

namespace Creational.FactoryMethodPattern
{
public class Program
{
public static void Main(string[] args)
{
CarFactory factory;
Car car;

factory = new HyundaiCarFactory();

car = factory.CreateCar("coupe");
Console.WriteLine($"Type: {car.GetType()}");

car = factory.CreateCar("i30");
Console.WriteLine($"Type: {car.GetType()}");

factory = new MazdaCarFactory();

car = factory.CreateCar("mx5");
Console.WriteLine($"Type: {car.GetType()}");

car = factory.CreateCar("6");
Console.WriteLine($"Type: {car.GetType()}");
}
}
}
using Creational.FactoryMethodPattern.Cars;
using Creational.FactoryMethodPattern.Factories;

namespace Creational.FactoryMethodPattern
{
public class Program
{
public static void Main(string[] args)
{
CarFactory factory;
Car car;

factory = new HyundaiCarFactory();

car = factory.CreateCar("coupe");
Console.WriteLine($"Type: {car.GetType()}");

car = factory.CreateCar("i30");
Console.WriteLine($"Type: {car.GetType()}");

factory = new MazdaCarFactory();

car = factory.CreateCar("mx5");
Console.WriteLine($"Type: {car.GetType()}");

car = factory.CreateCar("6");
Console.WriteLine($"Type: {car.GetType()}");
}
}
}
So what's the difference between this ^and that?
Pobiega
Pobiega13mo ago
welllllll this uses the factories so uh.. yeah, as said this example sucks 😄 this example very much just shows you what the code looks like, it doesnt show you why or when this pattern makes sense
Merineth
MerinethOP13mo ago
haha i juat have a really hard time understanding or relating to stuff when i’m not given concrete examples :( okay i took a quick nap D: If anyone sees this and wouldn't mind explaining Factory Method to me :sadcat: Anyone ? :/
namespace Creational.FactoryMethodPattern
{
public class Program
{
public static void Main(string[] args)
{
CarFactory factory;
Car car;

factory = new HyundaiCarFactory();

car = factory.CreateCar("coupe");
Console.WriteLine($"Type: {car.GetType()}");

car = factory.CreateCar("i30");
Console.WriteLine($"Type: {car.GetType()}");

factory = new MazdaCarFactory();

car = factory.CreateCar("mx5");
Console.WriteLine($"Type: {car.GetType()}");

car = factory.CreateCar("6");
Console.WriteLine($"Type: {car.GetType()}");
}
}
}

namespace Creational.FactoryMethodPattern.Factories
{
public abstract class CarFactory
{
public abstract Car CreateCar(string model);
}
}

namespace Creational.FactoryMethodPattern.Factories
{
public class HyundaiCarFactory : CarFactory
{
public override Car CreateCar(string model)
{
switch (model.ToLower())
{
case "coupe": return new HyundaiCoupe();
case "i30": return new HyundaiI30();
default: throw new ArgumentException("Invalid model", "model");
}
}
}
}

namespace Creational.FactoryMethodPattern.Factories
{
public class MazdaCarFactory : CarFactory
{
public override Car CreateCar(string model)
{
switch (model.ToLower())
{
case "mx5": return new MazdaMX5();
case "6": return new Mazda6();
default: throw new ArgumentException("Invalid model", "model");
}
}
}
}
namespace Creational.FactoryMethodPattern
{
public class Program
{
public static void Main(string[] args)
{
CarFactory factory;
Car car;

factory = new HyundaiCarFactory();

car = factory.CreateCar("coupe");
Console.WriteLine($"Type: {car.GetType()}");

car = factory.CreateCar("i30");
Console.WriteLine($"Type: {car.GetType()}");

factory = new MazdaCarFactory();

car = factory.CreateCar("mx5");
Console.WriteLine($"Type: {car.GetType()}");

car = factory.CreateCar("6");
Console.WriteLine($"Type: {car.GetType()}");
}
}
}

namespace Creational.FactoryMethodPattern.Factories
{
public abstract class CarFactory
{
public abstract Car CreateCar(string model);
}
}

namespace Creational.FactoryMethodPattern.Factories
{
public class HyundaiCarFactory : CarFactory
{
public override Car CreateCar(string model)
{
switch (model.ToLower())
{
case "coupe": return new HyundaiCoupe();
case "i30": return new HyundaiI30();
default: throw new ArgumentException("Invalid model", "model");
}
}
}
}

namespace Creational.FactoryMethodPattern.Factories
{
public class MazdaCarFactory : CarFactory
{
public override Car CreateCar(string model)
{
switch (model.ToLower())
{
case "mx5": return new MazdaMX5();
case "6": return new Mazda6();
default: throw new ArgumentException("Invalid model", "model");
}
}
}
}
This is the provided solution However it doesn't really bring me any closer in understand what factories do.
always say never
always say never13mo ago
i would use a factory for creating clients, for example
Merineth
MerinethOP13mo ago
How would that work? The only rough idea i have around factories are that they are using to encapsulate outside of the main method? As in the constructor isn't done in the main?
TizzyT
TizzyT13mo ago
static factory method <T> where T : WhatEverClassThisIs, new() 😛
always say never
always say never13mo ago
i would use for example as a helper to have some logic when instantiating a class
sealed class ClientFactory {
MySettings _settings;

static IClient CreateClient(SomePars somePars) {
var stuff = ProcessPars(somePars);
return new MyClient(_settings.ClientSettings, stuff);
}
}
sealed class ClientFactory {
MySettings _settings;

static IClient CreateClient(SomePars somePars) {
var stuff = ProcessPars(somePars);
return new MyClient(_settings.ClientSettings, stuff);
}
}
and then there could be other CreateClient methods with different parameters

Did you find this page helpful?