Recently I’ve been feeling the urge to study design patterns, memory and performance stuff in a more structured way. Here are my notes about the design pattern Factory Method. I’ll try to put it straightforward:
Factory Method
The description from Gang Of Four :
Define an interface for creating an object, but let sub-classes decide which class to instantiate. The Factory method lets a class defer instantiation it uses to sub-classes.
It looks like creating an abstract class as structure of objects, and then factory calls which objects to produce. It’s still not clear enough, what exactly does it mean?
Scenario:
Imagine that you are the factory manager and there are a list of products in the fruit factory. One day you want to request the factory for certain products, like “OK Factory, give me 2 organic strawberries and 2 California oranges”. Then the factory will produce and package these products for you in the next few hours.
Solution:
You could simply call constructors:
1 2 3 4 5 |
Stawberry s1 = new Stawberry(); Stawberry s2 = new Stawberry(); Orange o1 = new Orange(); Orange o2 = new Orange(); Orange o3 = new Orange(); |
And add them to your repository. It is OK but what if you need 1 million strawberries and 10 million oranges?
OR —
You could think this way, the products A, B, C… share some qualities (because they are all fruits) so they can be derived from the same class, let’s say PRODUCTS (so that fruits of sub-classes are polymorphous of PRODUCTS). Also, we want to keep it as simple as possible, where FACTORY could be something that encapsulates all these production details. Therefore in this way, the logic could be equivalent to:
1 |
MyFactory.Produce(Products product) |
You could also add a number to it:
1 |
MyFactory.Produce(Products product, int number) |
Great! This is a step closer to the Factory Method describe in Solution One++.
Solution++:
Factory Method is basically the logic of FACTORY – produces – PRODUCTS. PRODUCTS are things that we are creating, FACTORY is the method to produce these PRODUCTS.
From what’s discussed earlier, we already have a plan in mind:
1 |
MyFactory.Produce(Products product) |
Now it’s very clear that what we need is the Products class and MyFactory.Produce() method.
On the PRODUCTS side, an abstract class or interface is needed to then create sub-classes as actual products. This is just Polymorphism.
On the FACTORY side, we need to create a Produce method to get the PRODUCTS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
// Create Fruits classes, the things we are creating abstract public class Fruits { abstract public string Name() {get; } } public class Strawberry : Fruits { override public string Name() { return "Strawberry"; } } public class Orange : Fruits { override public string Name() { return "Orange"; } } // Create Factory class, the method we use to get those fruits public interface IFruitFactory { Fruits Produce(string fruitName); Fruits[] Produce(string fruitName, int number); } public class FruitFactory : IFruitFactory { // Factory Method - Produce single fruit public Fruits Produce(string fruitName) { switch(fruitName){ case "Strawberry" : return new Strawberry(); // return the specific instance of Fruits case "Orange": return new Orange(); default: ; } } // Factory Method - Produce multiple fruits public Fruits[] Produce(string fruitName, int number) { Fruits[] fruits = new Fruits[number]; switch(fruitName){ case "Strawberry" : { for(int i = 0; i < number; i++) { fruits[i] = new Strawberry(); } } case "Orange": { for(int i = 0; i < number; i++) { fruits[i] = new Orange(); } } default: ; } return fruits; } } // Example of using the Factory Method public static void Main() { var fruit = FruitFactory.Produce("Stawberry"); Console.WriteLine(fruit.Name()); var fruit = FruitFactory.Produce("Orange", 10); Console.WriteLine("The number of " + fruit.Name() + " is 10"); } |
WHY and WHEN to use Factory Method?
Compared to normal constructors, Factory Method is able to provide better encapsulation of the things to be created, and is clearer to the user about what and how many to instantiate. Constructors, however, are usually not explicit enough. Factory, as its name indicates, is something with all product information, no matter it is producing products or not, we can always turn to the Factory for what we need when we need it.
- Better encapsulation of product information
- More customization for instantiation, like quantities and colors…
- Better object-oriented concept, more explicit to users
HOW does it relate to game development?
Say we are making an garbage-collecting game, like Fallout, and there is a large inventory to manage. We would like to use certain tools when we need it, like knife, guns and bullets. Without having to remember what classes to instantiate, we would just need to create an Inventory as factory, call Inventory.Get(Tools tool) to acquire the things from the inventory. This is very useful especially if the inventory is very large with countless items.
Perks:
Difference between Interface and Abstract Class —
Interface methods are implemented, they don’t have any implementation yet so there is nothing to override. While abstract class methods (which are default to virtual methods) are overridden. Usually abstract class can have some implementations and some abstract methods, it cannot be instantiated.