In my opinion, both of these implementations violate at least a couple of rules, the principle of single responsibility (well, you could argue that he is responsible for creating, but IMO, that responsibility is too broad) and the Open / Closed principle (every time you add the form, you need to change the class). Not to mention that the first implementation does not allow you to provide parameters for constructors. The way that I usually solve this is to use the following approach:
public struct ShapeCreationSettings { public Predicate<string> Predicate; public Func<IShapeCreationParams, Shape> Creator; } public interface IShapeCreationParams {} public struct CircleCreationParams : IShapeCreationParams { public CircleCreationParams(int r) : this() { R = r; } public int R { get; private set; } } public struct SquareCreationParams : IShapeCreationParams { public SquareCreationParams(int a) : this() { A = a; } public int A { get; private set; } } public class ShapeFactory : IShapeFactory { protected static List<ShapeCreationSettings> settings = new List<ShapeCreationSettings>(); static ShapeFactory() { settings.Add(new ShapeCreationSettings { Predicate = t => t.Equals("Circle"), Creator = p => new Circle(((CircleCreationParams) p).R) }); settings.Add(new ShapeCreationSettings { Predicate = t => t.Equals("Square"), Creator = p => new Square(((SquareCreationParams)p).A) }); } public Shape Create(string name, IShapeCreationParams p) { return settings.FirstOrDefault(s => s.Predicate(name)).Creator(p); } }
For example, the creation settings are set using a static constructor, which still requires a class change; in a real scenario, I would add the AddSettings method for this or rely on the IoC container (if it provided such functionality).
By doing so, you have the advantage of loose coupling (you can change how objects are actually constructed during the separation process) and can add new types of shapes at any time convenient for you, without even having to rebuild the factory. In addition, you can provide designers with form-specific options for designers.
Of course, considering only this simple example of figure-building, this seems a little constructed, but I take this approach for more complex and realistic scenarios.
source share