Factory Design Template (criticism required)

I am compiling an explanation and sample code for this design pattern, trying to help others around me understand it (along with helping me deal with the pattern).

What I'm looking for is opinions and criticisms of my explanation and code example ... thanks!

What is a factory template? The factory template uses a dedicated object-to-object object to handle the creation and most instances of objects similar to the real world of factory.

Real world example
Think about the fact that the car factory is the creator of various types of cars. One of the assembly lines in this car factory can produce a truck one day, but on another day it can be redone to produce cars. Say a dealership places an order for 10 cars in its designated billing department. Then this department uses a specific factory and orders 10 cars. Account handlers do not care about making cars themselves (imagine poor results), they only work with the final product, ensuring that the dealership receives their vehicles.

A new model of the same car comes out next year, and orders begin to arrive. Account handlers (still not manufacturing cars) place orders, but now the car they receive is different, the assembly or even, possibly, the factory may be different, but account handlers should not worry about that. Additional thought: factory assemblers can know exactly what action should be taken if any account handler places an order (i.e., Account X handler places an order, factory assembler knows that they produce 10 transport for account X handler type Y products). Another option may be that the account handler tells the assembler exactly what type of vehicle should produce.

If the account handlers also handled the creation of vehicles (i.e. they were connected), each time the vehicle was changed in any way, each of the account handlers had to relearn when creating this vehicle. This will create quality problems, since there are far more account handlers than factories will be ... errors will occur, costs will be much greater.

Transition to OOP
The factory object as a design pattern used for software development is similar to the above example in the concept ... factory displays various types of other objects, you can use the assembly line (assembler object), which creates a certain type of object, returned in a certain way. The assembler can either check the requesting client and the descriptor, or the client can tell the assembler which object it requires. Now ... you are working on a project and creating a factory object and various assemblers, and then on the way in the project, the requirements change a bit, now you are asked to change the contents of the object and how its clients process this object, Since you used the factory template, this is a simple change , and in one place you can change or add objects created by the factory, and change the format in which collectors contain the contents of the object.

An unfortunate way to do this would be without the factory method, creating an instance of each instance of the object and the contents of the formatting content in the clients themselves ... let's say that you used this particular object in 20 clients. Now you have to go to each client, change each instance of the object and formats ... what a waste of time ... Take care ... do it right the first time so that you save yourself (and others) time and effort later.

Code Example (C #)
The following is an example of using a factory for food and various foods

Factory module public enum FoodType { //enumerated foodtype value, if client wants to specify type of object, coupling still occurs Hamburger, Pizza, HotDog }  /// <summary> /// Object to be overridden (logical) /// </summary> public abstract class Food { public abstract double FoodPrice { get; } }  /// <summary> /// Factory object to be overridden (logical) /// </summary> public abstract class FoodFactory { public abstract Food CreateFood(FoodType type); }  //------------------------------------------------------------------------- #region various food objects class Hamburger : Food { double _foodPrice = 3.59; public override double FoodPrice { get { return _foodPrice; } } }  class Pizza : Food { double _foodPrice = 2.49; public override double FoodPrice { get { return _foodPrice; } } }  class HotDog : Food { double _foodPrice = 1.49; public override double FoodPrice { get { return _foodPrice; } } } #endregion //--------------------------------------------------------------------------   /// <summary> /// Physical factory /// </summary> public class ConcreteFoodFactory : FoodFactory { public override Food CreateFood(FoodType foodType) { switch (foodType) { case FoodType.Hamburger: return new Hamburger(); break; case FoodType.HotDog: return new HotDog(); break; case FoodType.Pizza: return new Pizza(); break; default: return null; break; } } }  /// <summary> /// Assemblers /// </summary> public class FoodAssembler { public string AssembleFoodAsString(object sender, FoodFactory factory) { Food food = factory.CreateFood(FoodType.Hamburger); if (sender.GetType().Name == "default_aspx") { return string.Format("The price for the hamburger is: ${0}", food.FoodPrice.ToString()); } else { return food.FoodPrice.ToString(); } }  public Food AssembleFoodObject(FoodFactory factory) { Food food = factory.CreateFood(FoodType.Hamburger); return food; } } Calling factory FoodFactory factory = new ConcreteFoodFactory(); //create an instance of the factoryenter code here lblUser.Text = new FoodAssembler().AssembleFoodAsString(this, factory); //call the assembler which formats for string output Object o = new FoodAssembler().AssembleFoodObject(factory); //example: instantiating anon object, initialized with created food object 
+6
c # design-patterns factory-pattern
source share
3 answers

Unfortunately. This is a pretty diehard factory. Reflection may result in the death of some POWWAH !!

 public interface IFood { bool IsTasty { get; } } public class Hamburger : IFood { public bool IsTasty {get{ return true;}} } public class PeaSoup : IFood { public bool IsTasty { get { return false; } } } public class FoodFactory { private Dictionary<string, Type> _foundFoodTypes = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase); /// <summary> /// Scan all specified assemblies after food. /// </summary> public void ScanForFood(params Assembly[] assemblies) { var foodType = typeof (IFood); foreach (var assembly in assemblies) { foreach (var type in assembly.GetTypes()) { if (!foodType.IsAssignableFrom(type) || type.IsAbstract || type.IsInterface) continue; _foundFoodTypes.Add(type.Name, type); } } } /// <summary> /// Create some food! /// </summary> /// <param name="name"></param> /// <returns></returns> public IFood Create(string name) { Type type; if (!_foundFoodTypes.TryGetValue(name, out type)) throw new ArgumentException("Failed to find food named '" + name + "'."); return (IFood)Activator.CreateInstance(type); } } 

Using:

 var factory = new FoodFactory(); factory.ScanForFood(Assembly.GetExecutingAssembly()); Console.WriteLine("Is a hamburger tasty? " + factory.Create("Hamburger").IsTasty); 

Change, feedback on your code:

First of all, factories are used to create objects with minor code changes, as much as possible when adding new types of implementations. Using an enumeration means that all places that invoke the factory must use the enumeration and update when the enumeration changes.

Of course, this is slightly better than creating types directly.

The second problem with your code is that you are using a switch statement (but this is the best way to do this if the enumeration is a requirement). It is better to be able to register all the different classes in some way. Either from the configuration file, or by allowing actual implementations (such as the Hamburger class) to register. This requires the factory to follow the singleton pattern.

Here goes Reflection to the rescue. Reflection allows you to view all types in DLLs and EXEs. Thus, we can search for all classes that implement our interface, and therefore can create a dictionary for all classes.

+14
source share

I think your explanation, including an example of the real world, is good. However, I do not think your sample code shows the real benefits of the template.

Possible changes:

  • I would not have an enumeration in parallel with types. It looks like you need to update the enum every time the type is added. It might be more appropriate to pass System.Type. Then you can even make the factory common with the template argument.
  • I think the pattern is more β€œimpressive” if you use it to create something like a hardware interface. You will then have "AbstractNetworkDevice", and all your subscribers do not know what your hardware configuration is. But the factory can create "TcpNetworkDevice" or "SerialNetworkDevice" or something else based on some configuration that was made at startup.
+3
source share

I suggest you use interfaces instead of abstract classes / inheritance. Other than that, it looks normal.

0
source share

All Articles