Design Patterns / Factory Method

I'm having some serious issues understanding what the Factory method does. We were given an exercise to learn it but i'm completely lost on how / what it is that i have to do.
No description
No description
71 Replies
Merineth πŸ‡ΈπŸ‡ͺ
Like specifically the picture they provide doesn't really make sense to me. So far the only thing i know is that we use the "Factory Method" such that we don't instantiate a constructor directly into main. But we let the "factory" (w/e that is) do it for us. So what exactly are we meant to do in main? Call an interface/abstract class which in turn calls something?
Pobiega
Pobiegaβ€’4w ago
in main, you call your factory method. This gives you the object the factory created. There was a pretty good example at the end of your last thread
Merineth πŸ‡ΈπŸ‡ͺ
I sadly don't have my own thread open Or can't find it rather
Pobiega
Pobiegaβ€’4w ago
ok, here is an example
var factory = new ProductFactory();

List<Product> products = new()
{
factory.Create("Water Cup", 100),
factory.Create("Cheese", 200),
factory.Create("Cheesecake", 300),
};

foreach (var product in products)
{
Console.WriteLine($"Product {product.Id}: {product.Name} costs {product.Price} dollars");
}

public class ProductFactory
{
private int _id = 1;

public Product Create(string name, int price)
{
return new Product(_id++, name, price);
}
}

public record Product(int Id, string Name, int Price);
var factory = new ProductFactory();

List<Product> products = new()
{
factory.Create("Water Cup", 100),
factory.Create("Cheese", 200),
factory.Create("Cheesecake", 300),
};

foreach (var product in products)
{
Console.WriteLine($"Product {product.Id}: {product.Name} costs {product.Price} dollars");
}

public class ProductFactory
{
private int _id = 1;

public Product Create(string name, int price)
{
return new Product(_id++, name, price);
}
}

public record Product(int Id, string Name, int Price);
we have a Product class that has 3 properties: Id, Name and Price
Merineth πŸ‡ΈπŸ‡ͺ
And this is all inside main?
Pobiega
Pobiegaβ€’4w ago
no, just the stuff before public class ProductFactory we want Ids to be assigned automatically, so we make a factory that keeps track of IDs we then create instances of products via the factory, and they automatically get their IDs assigned and incremented
Merineth πŸ‡ΈπŸ‡ͺ
Ok. So we create an object from ProductFactoru().
List<Product> products = new()
{
factory.Create("Water Cup", 100),
factory.Create("Cheese", 200),
factory.Create("Cheesecake", 300),
};
List<Product> products = new()
{
factory.Create("Water Cup", 100),
factory.Create("Cheese", 200),
factory.Create("Cheesecake", 300),
};
I'm not sure what this does tho
Pobiega
Pobiegaβ€’4w ago
it creates a list it makes 3 products via the factory and adds them all to the list
Merineth πŸ‡ΈπŸ‡ͺ
I see. Is the list an array?
Pobiega
Pobiegaβ€’4w ago
its a List.
Merineth πŸ‡ΈπŸ‡ͺ
Never seen List<Product>Syntax before
Pobiega
Pobiegaβ€’4w ago
Product[] products =
[
factory.Create("Water Cup", 100),
factory.Create("Cheese", 200),
factory.Create("Cheesecake", 300)
];
Product[] products =
[
factory.Create("Water Cup", 100),
factory.Create("Cheese", 200),
factory.Create("Cheesecake", 300)
];
Merineth πŸ‡ΈπŸ‡ͺ
I know of all the basic ones like array, linked list, stack, heap etc..
Pobiega
Pobiegaβ€’4w ago
now its an array. happy? πŸ˜›
Merineth πŸ‡ΈπŸ‡ͺ
Yeah that makes sense Just wasn't aware c# had it's own type of list
Pobiega
Pobiegaβ€’4w ago
a List<T> is a smart wrapper around an array, and is used for when you dont know the size of the list ahead of time it uses an array internally, but has a lot of helper methods to automatically resize the array when needed
Merineth πŸ‡ΈπŸ‡ͺ
I see. Couldn't we just define the array like you did Product[]. This makes the Array scale with input? If the purpose of List<T> is used for when we don't know the size of the array. Shouldn't Product[] do the same thing? Also where is the abstract class / interface in this example?
Pobiega
Pobiegaβ€’4w ago
there is none.
Merineth πŸ‡ΈπŸ‡ͺ
So the factory method doesn't always have an interface/abstract class?
Pobiega
Pobiegaβ€’4w ago
no. you are probably mixing the two patterns up again
Merineth πŸ‡ΈπŸ‡ͺ
:harold:
Pobiega
Pobiegaβ€’4w ago
there is a pattenr called ABSTRACT FACTORY and one called FACTORY :p
Merineth πŸ‡ΈπŸ‡ͺ
Oh. I had no idea that was the case But it seems this exercise is asking to use the Factory Method
Merineth πŸ‡ΈπŸ‡ͺ
So what are the differences between these classes?
No description
Pobiega
Pobiegaβ€’4w ago
that picture is for the abstract factory
Merineth πŸ‡ΈπŸ‡ͺ
Because in my exercise we have two type of brands of cars. Hyundai and Mazda. And these two brands have 2 types each. HyundaiCoupe, Hyundail30 and Mazda6, MazdaMX5. So would i need two types of factories one for Hyundai and one for Mazda?
Pobiega
Pobiegaβ€’4w ago
yeah welllll it depends on several things
Merineth πŸ‡ΈπŸ‡ͺ
Really? The exercise is described as "Factory Method" and it says FactoryBaseShould be an interface/abstract method
Pobiega
Pobiegaβ€’4w ago
you could in theory just have a single factory with 4 methods, but thats not very scaleable FactoryBase is literally an abstract class, so yes.
Merineth πŸ‡ΈπŸ‡ͺ
Ok. And this abstract class should contain the two Concrete Factories? Which is Mazda and Hyundai
Pobiega
Pobiegaβ€’4w ago
no it doesnt contain them they are subclasses of it
Merineth πŸ‡ΈπŸ‡ͺ
Yeah sorry meant subclass And these subclasses are the one that makes the cars?
Pobiega
Pobiegaβ€’4w ago
yes
Merineth πŸ‡ΈπŸ‡ͺ
And that is essentially it?
Pobiega
Pobiegaβ€’4w ago
they are the ConcreteFactories
Merineth πŸ‡ΈπŸ‡ͺ
Aah i see! And they make the ConcreteProduct ?
Pobiega
Pobiegaβ€’4w ago
yes
Merineth πŸ‡ΈπŸ‡ͺ
What is the ProductBaseFor?
Pobiega
Pobiegaβ€’4w ago
public abstract class FactoryBase
{
public abstract Car Create();
}

public class HyundaiFactory : FactoryBase
{
public override Hyundai Create()
{
return new Hyundai("Hyundai");
}
}
public abstract class FactoryBase
{
public abstract Car Create();
}

public class HyundaiFactory : FactoryBase
{
public override Hyundai Create()
{
return new Hyundai("Hyundai");
}
}
for the abstract factory to know what to make
Pobiega
Pobiegaβ€’4w ago
No description
Pobiega
Pobiegaβ€’4w ago
you can see how the two structures mirror eachother
Merineth πŸ‡ΈπŸ‡ͺ
Ah yeah So the right one is An abstract Factory and left one is a normal Factory?
Pobiega
Pobiegaβ€’4w ago
>_> the left ones are the products the cars the right ones are the factories the top one is the factoryBase, the abstract factory the bottom ones are the concrete factories
Merineth πŸ‡ΈπŸ‡ͺ
This is so abstract, it's extremely tough to understand
Pobiega
Pobiegaβ€’4w ago
public abstract class FactoryBase
{
public abstract Car Create(string name);
}

public class HyundaiFactory : FactoryBase
{
public override Hyundai Create(string name)
{
return name switch
{
"Coupe" => new HyundaiCoupe(),
"IL30" => new HyundaiIL30(),
_ => throw new ArgumentException($"Invalid hyundai model name {name}")
};
}
}

public class MazdaFactory : FactoryBase
{
public override Mazda Create(string name)
{
return name switch
{
"3" => new Mazda3(),
"MX5" => new MazdaMX5(),
_ => throw new ArgumentException($"Invalid mazda model name {name}")
};
}
}

public abstract record Car;
public record Mazda(string Name) : Car;
public record Mazda3() : Mazda("3");
public record MazdaMX5() : Mazda("MX5");
public record Hyundai(string Name) : Car;
public record HyundaiCoupe() : Hyundai("Coupe");
public record HyundaiIL30() : Hyundai("IL30");
public abstract class FactoryBase
{
public abstract Car Create(string name);
}

public class HyundaiFactory : FactoryBase
{
public override Hyundai Create(string name)
{
return name switch
{
"Coupe" => new HyundaiCoupe(),
"IL30" => new HyundaiIL30(),
_ => throw new ArgumentException($"Invalid hyundai model name {name}")
};
}
}

public class MazdaFactory : FactoryBase
{
public override Mazda Create(string name)
{
return name switch
{
"3" => new Mazda3(),
"MX5" => new MazdaMX5(),
_ => throw new ArgumentException($"Invalid mazda model name {name}")
};
}
}

public abstract record Car;
public record Mazda(string Name) : Car;
public record Mazda3() : Mazda("3");
public record MazdaMX5() : Mazda("MX5");
public record Hyundai(string Name) : Car;
public record HyundaiCoupe() : Hyundai("Coupe");
public record HyundaiIL30() : Hyundai("IL30");
does this help? we have 2 concrete factories, that make specific cars we have the abstract factory that they both inherit from
Pobiega
Pobiegaβ€’4w ago
yeah thats exactly what we have here
Merineth πŸ‡ΈπŸ‡ͺ
And the stringname is the parameter which decides which car to make? Or rather which concrete Factory to enter?
Pobiega
Pobiegaβ€’4w ago
yes to the first one, no to the second one
Merineth πŸ‡ΈπŸ‡ͺ
Just to go through it, making sure i get it right.
public abstract class FactoryBase
{
public abstract Car Create(string name);
}
public abstract class FactoryBase
{
public abstract Car Create(string name);
}
So we call the Create method with the argument string name? How does it know which one concrete factory to enter?
Pobiega
Pobiegaβ€’4w ago
it doesnt you cant have an instance of FactoryBase its impossible
Merineth πŸ‡ΈπŸ‡ͺ
Right, i'm onboard with that. I'm just curious to what happens when we call the method Create. Since Create is defined in both factories.
Pobiega
Pobiegaβ€’4w ago
well, Create is an instance method its called on the instance of the factory and since we cant make instances of FactoryBase, its only called on a concrete factory so we already know if its a mazda or a hyundai factory
Merineth πŸ‡ΈπŸ‡ͺ
I'm not sure i understand that part. I was taught that when we call on a method such as car Create() it will call that specific method and apply everything inside the {}. However Create() is defined inside both factories. So how does C# know which factory to enter? Does it enter both of them? Or does it go to the appropriate one based on the argument inside create() ?
Pobiega
Pobiegaβ€’4w ago
Show me the code you are thinking about alternatively, do you have a headset at hand and can jump into a VC? I could show you via screenshare exactly how this works.
Merineth πŸ‡ΈπŸ‡ͺ
public abstract class FactoryBase
{
public abstract Car Create(string name);
}

public class HyundaiFactory : FactoryBase
{
public override Hyundai Create(string name)
{
return name switch
{
"Coupe" => new HyundaiCoupe(),
"IL30" => new HyundaiIL30(),
_ => throw new ArgumentException($"Invalid hyundai model name {name}")
};
}
}

public class MazdaFactory : FactoryBase
{
public override Mazda Create(string name)
{
return name switch
{
"3" => new Mazda3(),
"MX5" => new MazdaMX5(),
_ => throw new ArgumentException($"Invalid mazda model name {name}")
};
}
}
public abstract class FactoryBase
{
public abstract Car Create(string name);
}

public class HyundaiFactory : FactoryBase
{
public override Hyundai Create(string name)
{
return name switch
{
"Coupe" => new HyundaiCoupe(),
"IL30" => new HyundaiIL30(),
_ => throw new ArgumentException($"Invalid hyundai model name {name}")
};
}
}

public class MazdaFactory : FactoryBase
{
public override Mazda Create(string name)
{
return name switch
{
"3" => new Mazda3(),
"MX5" => new MazdaMX5(),
_ => throw new ArgumentException($"Invalid mazda model name {name}")
};
}
}
This is what i'm basing it of. When we call the method create from public abstract Car Create(string name);. Both MazdaFactoryand HyundaiFactory has the method Create. So which one will it enter?
Pobiega
Pobiegaβ€’4w ago
neither it cant you cant do what you are saying
Merineth πŸ‡ΈπŸ‡ͺ
methods work differently inside abstract classes? Essentially what i'm asking is: What happens when public abstract Car Create(string name); is called
Pobiega
Pobiegaβ€’4w ago
no, but in that code you just pasted, there is no method call can you write out the method call show me HOW you would invoke that method
Merineth πŸ‡ΈπŸ‡ͺ
public abstract Car Create(string name); public abstract Car Create(string name);this is a method?
Pobiega
Pobiegaβ€’4w ago
yes but its an abstract method that particular method will never be called.
Merineth πŸ‡ΈπŸ‡ͺ
Oh so we aren't actually invoking it inside the abstract class?
Pobiega
Pobiegaβ€’4w ago
there are no invocations anywhere here
Merineth πŸ‡ΈπŸ‡ͺ
Shit
Pobiega
Pobiegaβ€’4w ago
its just declarations
Merineth πŸ‡ΈπŸ‡ͺ
Okay that's why i'm confused lmao
Pobiega
Pobiegaβ€’4w ago
invocations are the stuff you'd see in "main"
Merineth πŸ‡ΈπŸ‡ͺ
I assumed it was an invocation of it So if i were to invoke it inside main
Create(string Coupe);
Create(string Coupe);
Pobiega
Pobiegaβ€’4w ago
look, can you jump on a screenshare call right now? it'd be easier to show
Merineth πŸ‡ΈπŸ‡ͺ
Sure
Pobiega
Pobiegaβ€’4w ago
#vc-3
Want results from more Discord servers?
Add your server